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

Side by Side Diff: src/compiler/js-native-context-specialization.cc

Issue 1425293004: [turbofan] Add support for named access to Number primitives. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Created 5 years, 1 month 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/js-native-context-specialization.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 336 matching lines...) Expand 10 before | Expand all | Expand 10 after
347 Node* check = graph()->NewNode(simplified()->ReferenceEqual(Type::Name()), 347 Node* check = graph()->NewNode(simplified()->ReferenceEqual(Type::Name()),
348 index, jsgraph()->HeapConstant(name)); 348 index, jsgraph()->HeapConstant(name));
349 Node* branch = 349 Node* branch =
350 graph()->NewNode(common()->Branch(BranchHint::kTrue), check, control); 350 graph()->NewNode(common()->Branch(BranchHint::kTrue), check, control);
351 exit_controls.push_back(graph()->NewNode(common()->IfFalse(), branch)); 351 exit_controls.push_back(graph()->NewNode(common()->IfFalse(), branch));
352 control = graph()->NewNode(common()->IfTrue(), branch); 352 control = graph()->NewNode(common()->IfTrue(), branch);
353 } 353 }
354 354
355 // Ensure that {receiver} is a heap object. 355 // Ensure that {receiver} is a heap object.
356 Node* check = graph()->NewNode(simplified()->ObjectIsSmi(), receiver); 356 Node* check = graph()->NewNode(simplified()->ObjectIsSmi(), receiver);
357 Node* branch = 357 Node* branch = graph()->NewNode(common()->Branch(), check, control);
358 graph()->NewNode(common()->Branch(BranchHint::kFalse), check, control);
359 exit_controls.push_back(graph()->NewNode(common()->IfTrue(), branch));
360 control = graph()->NewNode(common()->IfFalse(), branch); 358 control = graph()->NewNode(common()->IfFalse(), branch);
359 Node* receiverissmi_control = graph()->NewNode(common()->IfTrue(), branch);
360 Node* receiverissmi_effect = effect;
361 361
362 // Load the {receiver} map. The resulting effect is the dominating effect for 362 // Load the {receiver} map. The resulting effect is the dominating effect for
363 // all (polymorphic) branches. 363 // all (polymorphic) branches.
364 Node* receiver_map = effect = 364 Node* receiver_map = effect =
365 graph()->NewNode(simplified()->LoadField(AccessBuilder::ForMap()), 365 graph()->NewNode(simplified()->LoadField(AccessBuilder::ForMap()),
366 receiver, effect, control); 366 receiver, effect, control);
367 367
368 // Generate code for the various different property access patterns. 368 // Generate code for the various different property access patterns.
369 Node* fallthrough_control = control; 369 Node* fallthrough_control = control;
370 for (PropertyAccessInfo const& access_info : access_infos) { 370 for (PropertyAccessInfo const& access_info : access_infos) {
(...skipping 10 matching lines...) Expand all
381 simplified()->LoadField(AccessBuilder::ForMapInstanceType()), 381 simplified()->LoadField(AccessBuilder::ForMapInstanceType()),
382 receiver_map, this_effect, fallthrough_control); 382 receiver_map, this_effect, fallthrough_control);
383 Node* check = 383 Node* check =
384 graph()->NewNode(machine()->Uint32LessThan(), receiver_instance_type, 384 graph()->NewNode(machine()->Uint32LessThan(), receiver_instance_type,
385 jsgraph()->Uint32Constant(FIRST_NONSTRING_TYPE)); 385 jsgraph()->Uint32Constant(FIRST_NONSTRING_TYPE));
386 Node* branch = 386 Node* branch =
387 graph()->NewNode(common()->Branch(), check, fallthrough_control); 387 graph()->NewNode(common()->Branch(), check, fallthrough_control);
388 fallthrough_control = graph()->NewNode(common()->IfFalse(), branch); 388 fallthrough_control = graph()->NewNode(common()->IfFalse(), branch);
389 this_control = graph()->NewNode(common()->IfTrue(), branch); 389 this_control = graph()->NewNode(common()->IfTrue(), branch);
390 } else { 390 } else {
391 // Emit a (sequence of) map checks for other properties. 391 // Emit a (sequence of) map checks for other {receiver}s.
392 ZoneVector<Node*> this_controls(zone()); 392 ZoneVector<Node*> this_controls(zone());
393 ZoneVector<Node*> this_effects(zone());
393 for (auto i = access_info.receiver_type()->Classes(); !i.Done(); 394 for (auto i = access_info.receiver_type()->Classes(); !i.Done();
394 i.Advance()) { 395 i.Advance()) {
395 Handle<Map> map = i.Current(); 396 Handle<Map> map = i.Current();
396 Node* check = 397 Node* check =
397 graph()->NewNode(simplified()->ReferenceEqual(Type::Internal()), 398 graph()->NewNode(simplified()->ReferenceEqual(Type::Internal()),
398 receiver_map, jsgraph()->Constant(map)); 399 receiver_map, jsgraph()->Constant(map));
399 Node* branch = 400 Node* branch =
400 graph()->NewNode(common()->Branch(), check, fallthrough_control); 401 graph()->NewNode(common()->Branch(), check, fallthrough_control);
402 fallthrough_control = graph()->NewNode(common()->IfFalse(), branch);
401 this_controls.push_back(graph()->NewNode(common()->IfTrue(), branch)); 403 this_controls.push_back(graph()->NewNode(common()->IfTrue(), branch));
402 fallthrough_control = graph()->NewNode(common()->IfFalse(), branch); 404 this_effects.push_back(this_effect);
403 } 405 }
406
407 // The Number case requires special treatment to also deal with Smis.
408 if (receiver_type->Is(Type::Number())) {
409 // Join this check with the "receiver is smi" check above, and mark the
410 // "receiver is smi" check as "consumed" so that we don't deoptimize if
411 // the {receiver} is actually a Smi.
412 if (receiverissmi_control != nullptr) {
413 this_controls.push_back(receiverissmi_control);
414 this_effects.push_back(receiverissmi_effect);
415 receiverissmi_control = receiverissmi_effect = nullptr;
416 }
417 }
418
419 // Create dominating Merge+EffectPhi for this {receiver} type.
404 int const this_control_count = static_cast<int>(this_controls.size()); 420 int const this_control_count = static_cast<int>(this_controls.size());
405 this_control = 421 this_control =
406 (this_control_count == 1) 422 (this_control_count == 1)
407 ? this_controls.front() 423 ? this_controls.front()
408 : graph()->NewNode(common()->Merge(this_control_count), 424 : graph()->NewNode(common()->Merge(this_control_count),
409 this_control_count, &this_controls.front()); 425 this_control_count, &this_controls.front());
426 this_effects.push_back(this_control);
427 int const this_effect_count = static_cast<int>(this_effects.size());
428 this_effect =
429 (this_control_count == 1)
430 ? this_effects.front()
431 : graph()->NewNode(common()->EffectPhi(this_control_count),
432 this_effect_count, &this_effects.front());
410 } 433 }
411 434
412 // Determine actual holder and perform prototype chain checks. 435 // Determine actual holder and perform prototype chain checks.
413 Handle<JSObject> holder; 436 Handle<JSObject> holder;
414 if (access_info.holder().ToHandle(&holder)) { 437 if (access_info.holder().ToHandle(&holder)) {
415 AssumePrototypesStable(receiver_type, holder); 438 AssumePrototypesStable(receiver_type, holder);
416 } 439 }
417 440
418 // Generate the actual property access. 441 // Generate the actual property access.
419 if (access_info.IsNotFound()) { 442 if (access_info.IsNotFound()) {
(...skipping 157 matching lines...) Expand 10 before | Expand all | Expand 10 after
577 600
578 // Remember the final state for this property access. 601 // Remember the final state for this property access.
579 values.push_back(this_value); 602 values.push_back(this_value);
580 effects.push_back(this_effect); 603 effects.push_back(this_effect);
581 controls.push_back(this_control); 604 controls.push_back(this_control);
582 } 605 }
583 606
584 // Collect the fallthrough control as final "exit" control. 607 // Collect the fallthrough control as final "exit" control.
585 if (fallthrough_control != control) { 608 if (fallthrough_control != control) {
586 // Mark the last fallthrough branch as deferred. 609 // Mark the last fallthrough branch as deferred.
587 Node* branch = NodeProperties::GetControlInput(fallthrough_control); 610 MarkAsDeferred(fallthrough_control);
588 DCHECK_EQ(IrOpcode::kBranch, branch->opcode());
589 if (fallthrough_control->opcode() == IrOpcode::kIfTrue) {
590 NodeProperties::ChangeOp(branch, common()->Branch(BranchHint::kFalse));
591 } else {
592 DCHECK_EQ(IrOpcode::kIfFalse, fallthrough_control->opcode());
593 NodeProperties::ChangeOp(branch, common()->Branch(BranchHint::kTrue));
594 }
595 } 611 }
596 exit_controls.push_back(fallthrough_control); 612 exit_controls.push_back(fallthrough_control);
597 613
614 // Also collect the "receiver is smi" control if we didn't handle the case of
615 // Number primitives in the polymorphic branches above.
616 if (receiverissmi_control != nullptr) {
617 // Mark the "receiver is smi" case as deferred.
618 MarkAsDeferred(receiverissmi_control);
619 DCHECK_EQ(exit_effect, receiverissmi_effect);
620 exit_controls.push_back(receiverissmi_control);
621 }
622
598 // Generate the single "exit" point, where we get if either all map/instance 623 // Generate the single "exit" point, where we get if either all map/instance
599 // type checks failed, or one of the assumptions inside one of the cases 624 // type checks failed, or one of the assumptions inside one of the cases
600 // failes (i.e. failing prototype chain check). 625 // failes (i.e. failing prototype chain check).
601 // TODO(bmeurer): Consider falling back to IC here if deoptimization is 626 // TODO(bmeurer): Consider falling back to IC here if deoptimization is
602 // disabled. 627 // disabled.
603 int const exit_control_count = static_cast<int>(exit_controls.size()); 628 int const exit_control_count = static_cast<int>(exit_controls.size());
604 Node* exit_control = 629 Node* exit_control =
605 (exit_control_count == 1) 630 (exit_control_count == 1)
606 ? exit_controls.front() 631 ? exit_controls.front()
607 : graph()->NewNode(common()->Merge(exit_control_count), 632 : graph()->NewNode(common()->Merge(exit_control_count),
(...skipping 261 matching lines...) Expand 10 before | Expand all | Expand 10 after
869 894
870 // Remember the final state for this element access. 895 // Remember the final state for this element access.
871 values.push_back(this_value); 896 values.push_back(this_value);
872 effects.push_back(this_effect); 897 effects.push_back(this_effect);
873 controls.push_back(this_control); 898 controls.push_back(this_control);
874 } 899 }
875 900
876 // Collect the fallthrough control as final "exit" control. 901 // Collect the fallthrough control as final "exit" control.
877 if (fallthrough_control != control) { 902 if (fallthrough_control != control) {
878 // Mark the last fallthrough branch as deferred. 903 // Mark the last fallthrough branch as deferred.
879 Node* branch = NodeProperties::GetControlInput(fallthrough_control); 904 MarkAsDeferred(fallthrough_control);
880 DCHECK_EQ(IrOpcode::kBranch, branch->opcode());
881 if (fallthrough_control->opcode() == IrOpcode::kIfTrue) {
882 NodeProperties::ChangeOp(branch, common()->Branch(BranchHint::kFalse));
883 } else {
884 DCHECK_EQ(IrOpcode::kIfFalse, fallthrough_control->opcode());
885 NodeProperties::ChangeOp(branch, common()->Branch(BranchHint::kTrue));
886 }
887 } 905 }
888 exit_controls.push_back(fallthrough_control); 906 exit_controls.push_back(fallthrough_control);
889 907
890 // Generate the single "exit" point, where we get if either all map/instance 908 // Generate the single "exit" point, where we get if either all map/instance
891 // type checks failed, or one of the assumptions inside one of the cases 909 // type checks failed, or one of the assumptions inside one of the cases
892 // failes (i.e. failing prototype chain check). 910 // failes (i.e. failing prototype chain check).
893 // TODO(bmeurer): Consider falling back to IC here if deoptimization is 911 // TODO(bmeurer): Consider falling back to IC here if deoptimization is
894 // disabled. 912 // disabled.
895 int const exit_control_count = static_cast<int>(exit_controls.size()); 913 int const exit_control_count = static_cast<int>(exit_controls.size());
896 Node* exit_control = 914 Node* exit_control =
(...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after
1046 Handle<JSReceiver> const prototype = 1064 Handle<JSReceiver> const prototype =
1047 PrototypeIterator::GetCurrent<JSReceiver>(j); 1065 PrototypeIterator::GetCurrent<JSReceiver>(j);
1048 dependencies()->AssumeMapStable(handle(prototype->map(), isolate())); 1066 dependencies()->AssumeMapStable(handle(prototype->map(), isolate()));
1049 // Stop once we get to the holder. 1067 // Stop once we get to the holder.
1050 if (prototype.is_identical_to(holder)) break; 1068 if (prototype.is_identical_to(holder)) break;
1051 } 1069 }
1052 } 1070 }
1053 } 1071 }
1054 1072
1055 1073
1074 void JSNativeContextSpecialization::MarkAsDeferred(Node* if_projection) {
1075 Node* branch = NodeProperties::GetControlInput(if_projection);
1076 DCHECK_EQ(IrOpcode::kBranch, branch->opcode());
1077 if (if_projection->opcode() == IrOpcode::kIfTrue) {
1078 NodeProperties::ChangeOp(branch, common()->Branch(BranchHint::kFalse));
1079 } else {
1080 DCHECK_EQ(IrOpcode::kIfFalse, if_projection->opcode());
1081 NodeProperties::ChangeOp(branch, common()->Branch(BranchHint::kTrue));
1082 }
1083 }
1084
1085
1056 Graph* JSNativeContextSpecialization::graph() const { 1086 Graph* JSNativeContextSpecialization::graph() const {
1057 return jsgraph()->graph(); 1087 return jsgraph()->graph();
1058 } 1088 }
1059 1089
1060 1090
1061 Isolate* JSNativeContextSpecialization::isolate() const { 1091 Isolate* JSNativeContextSpecialization::isolate() const {
1062 return jsgraph()->isolate(); 1092 return jsgraph()->isolate();
1063 } 1093 }
1064 1094
1065 1095
(...skipping 17 matching lines...) Expand all
1083 } 1113 }
1084 1114
1085 1115
1086 SimplifiedOperatorBuilder* JSNativeContextSpecialization::simplified() const { 1116 SimplifiedOperatorBuilder* JSNativeContextSpecialization::simplified() const {
1087 return jsgraph()->simplified(); 1117 return jsgraph()->simplified();
1088 } 1118 }
1089 1119
1090 } // namespace compiler 1120 } // namespace compiler
1091 } // namespace internal 1121 } // namespace internal
1092 } // namespace v8 1122 } // namespace v8
OLDNEW
« no previous file with comments | « src/compiler/js-native-context-specialization.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698