| 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-call-reducer.h" | 5 #include "src/compiler/js-call-reducer.h" |
| 6 | 6 |
| 7 #include "src/code-factory.h" | 7 #include "src/code-factory.h" |
| 8 #include "src/code-stubs.h" | 8 #include "src/code-stubs.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" |
| 11 #include "src/compiler/js-graph.h" | 11 #include "src/compiler/js-graph.h" |
| 12 #include "src/compiler/linkage.h" | 12 #include "src/compiler/linkage.h" |
| 13 #include "src/compiler/node-matchers.h" | 13 #include "src/compiler/node-matchers.h" |
| 14 #include "src/compiler/simplified-operator.h" | 14 #include "src/compiler/simplified-operator.h" |
| 15 #include "src/feedback-vector-inl.h" | 15 #include "src/feedback-vector-inl.h" |
| 16 #include "src/ic/call-optimization.h" | 16 #include "src/ic/call-optimization.h" |
| 17 #include "src/objects-inl.h" | 17 #include "src/objects-inl.h" |
| 18 | 18 |
| 19 namespace v8 { | 19 namespace v8 { |
| 20 namespace internal { | 20 namespace internal { |
| 21 namespace compiler { | 21 namespace compiler { |
| 22 | 22 |
| 23 Reduction JSCallReducer::Reduce(Node* node) { | 23 Reduction JSCallReducer::Reduce(Node* node) { |
| 24 switch (node->opcode()) { | 24 switch (node->opcode()) { |
| 25 case IrOpcode::kJSConstruct: | 25 case IrOpcode::kJSConstruct: |
| 26 return ReduceJSConstruct(node); | 26 return ReduceJSConstruct(node); |
| 27 case IrOpcode::kJSConstructWithArrayLike: |
| 28 return ReduceJSConstructWithArrayLike(node); |
| 27 case IrOpcode::kJSConstructWithSpread: | 29 case IrOpcode::kJSConstructWithSpread: |
| 28 return ReduceJSConstructWithSpread(node); | 30 return ReduceJSConstructWithSpread(node); |
| 29 case IrOpcode::kJSCall: | 31 case IrOpcode::kJSCall: |
| 30 return ReduceJSCall(node); | 32 return ReduceJSCall(node); |
| 31 case IrOpcode::kJSCallWithArrayLike: | 33 case IrOpcode::kJSCallWithArrayLike: |
| 32 return ReduceJSCallWithArrayLike(node); | 34 return ReduceJSCallWithArrayLike(node); |
| 33 case IrOpcode::kJSCallWithSpread: | 35 case IrOpcode::kJSCallWithSpread: |
| 34 return ReduceJSCallWithSpread(node); | 36 return ReduceJSCallWithSpread(node); |
| 35 default: | 37 default: |
| 36 break; | 38 break; |
| (...skipping 392 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 429 } | 431 } |
| 430 while (arity-- > 3) { | 432 while (arity-- > 3) { |
| 431 node->RemoveInput(arity); | 433 node->RemoveInput(arity); |
| 432 } | 434 } |
| 433 NodeProperties::ChangeOp(node, | 435 NodeProperties::ChangeOp(node, |
| 434 javascript()->CallWithArrayLike(p.frequency())); | 436 javascript()->CallWithArrayLike(p.frequency())); |
| 435 Reduction const reduction = ReduceJSCallWithArrayLike(node); | 437 Reduction const reduction = ReduceJSCallWithArrayLike(node); |
| 436 return reduction.Changed() ? reduction : Changed(node); | 438 return reduction.Changed() ? reduction : Changed(node); |
| 437 } | 439 } |
| 438 | 440 |
| 441 // ES6 section 26.1.2 Reflect.construct ( target, argumentsList [, newTarget] ) |
| 442 Reduction JSCallReducer::ReduceReflectConstruct(Node* node) { |
| 443 DCHECK_EQ(IrOpcode::kJSCall, node->opcode()); |
| 444 CallParameters const& p = CallParametersOf(node->op()); |
| 445 int arity = static_cast<int>(p.arity() - 2); |
| 446 DCHECK_LE(0, arity); |
| 447 // Massage value inputs appropriately. |
| 448 node->RemoveInput(0); |
| 449 node->RemoveInput(0); |
| 450 while (arity < 2) { |
| 451 node->InsertInput(graph()->zone(), arity++, jsgraph()->UndefinedConstant()); |
| 452 } |
| 453 if (arity < 3) { |
| 454 node->InsertInput(graph()->zone(), arity++, node->InputAt(0)); |
| 455 } |
| 456 while (arity-- > 3) { |
| 457 node->RemoveInput(arity); |
| 458 } |
| 459 NodeProperties::ChangeOp(node, |
| 460 javascript()->ConstructWithArrayLike(p.frequency())); |
| 461 Reduction const reduction = ReduceJSConstructWithArrayLike(node); |
| 462 return reduction.Changed() ? reduction : Changed(node); |
| 463 } |
| 464 |
| 439 // ES6 section 26.1.7 Reflect.getPrototypeOf ( target ) | 465 // ES6 section 26.1.7 Reflect.getPrototypeOf ( target ) |
| 440 Reduction JSCallReducer::ReduceReflectGetPrototypeOf(Node* node) { | 466 Reduction JSCallReducer::ReduceReflectGetPrototypeOf(Node* node) { |
| 441 DCHECK_EQ(IrOpcode::kJSCall, node->opcode()); | 467 DCHECK_EQ(IrOpcode::kJSCall, node->opcode()); |
| 442 Node* target = (node->op()->ValueInputCount() >= 3) | 468 Node* target = (node->op()->ValueInputCount() >= 3) |
| 443 ? NodeProperties::GetValueInput(node, 2) | 469 ? NodeProperties::GetValueInput(node, 2) |
| 444 : jsgraph()->UndefinedConstant(); | 470 : jsgraph()->UndefinedConstant(); |
| 445 return ReduceObjectGetPrototype(node, target); | 471 return ReduceObjectGetPrototype(node, target); |
| 446 } | 472 } |
| 447 | 473 |
| 448 Reduction JSCallReducer::ReduceArrayForEach(Handle<JSFunction> function, | 474 Reduction JSCallReducer::ReduceArrayForEach(Handle<JSFunction> function, |
| (...skipping 208 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 657 jsgraph()->ExternalConstant(function_reference)); | 683 jsgraph()->ExternalConstant(function_reference)); |
| 658 node->ReplaceInput(5, receiver); | 684 node->ReplaceInput(5, receiver); |
| 659 NodeProperties::ChangeOp(node, common()->Call(call_descriptor)); | 685 NodeProperties::ChangeOp(node, common()->Call(call_descriptor)); |
| 660 return Changed(node); | 686 return Changed(node); |
| 661 } | 687 } |
| 662 | 688 |
| 663 Reduction JSCallReducer::ReduceCallOrConstructWithArrayLikeOrSpread( | 689 Reduction JSCallReducer::ReduceCallOrConstructWithArrayLikeOrSpread( |
| 664 Node* node, int arity, CallFrequency const& frequency) { | 690 Node* node, int arity, CallFrequency const& frequency) { |
| 665 DCHECK(node->opcode() == IrOpcode::kJSCallWithArrayLike || | 691 DCHECK(node->opcode() == IrOpcode::kJSCallWithArrayLike || |
| 666 node->opcode() == IrOpcode::kJSCallWithSpread || | 692 node->opcode() == IrOpcode::kJSCallWithSpread || |
| 693 node->opcode() == IrOpcode::kJSConstructWithArrayLike || |
| 667 node->opcode() == IrOpcode::kJSConstructWithSpread); | 694 node->opcode() == IrOpcode::kJSConstructWithSpread); |
| 668 | 695 |
| 669 // In case of a call/construct with spread, we need to | 696 // In case of a call/construct with spread, we need to |
| 670 // ensure that it's safe to avoid the actual iteration. | 697 // ensure that it's safe to avoid the actual iteration. |
| 671 if ((node->opcode() == IrOpcode::kJSCallWithSpread || | 698 if ((node->opcode() == IrOpcode::kJSCallWithSpread || |
| 672 node->opcode() == IrOpcode::kJSConstructWithSpread) && | 699 node->opcode() == IrOpcode::kJSConstructWithSpread) && |
| 673 !isolate()->initial_array_iterator_prototype_map()->is_stable()) { | 700 !isolate()->initial_array_iterator_prototype_map()->is_stable()) { |
| 674 return NoChange(); | 701 return NoChange(); |
| 675 } | 702 } |
| 676 | 703 |
| (...skipping 171 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 848 case Builtins::kNumberConstructor: | 875 case Builtins::kNumberConstructor: |
| 849 return ReduceNumberConstructor(node); | 876 return ReduceNumberConstructor(node); |
| 850 case Builtins::kObjectGetPrototypeOf: | 877 case Builtins::kObjectGetPrototypeOf: |
| 851 return ReduceObjectGetPrototypeOf(node); | 878 return ReduceObjectGetPrototypeOf(node); |
| 852 case Builtins::kObjectPrototypeGetProto: | 879 case Builtins::kObjectPrototypeGetProto: |
| 853 return ReduceObjectPrototypeGetProto(node); | 880 return ReduceObjectPrototypeGetProto(node); |
| 854 case Builtins::kObjectPrototypeIsPrototypeOf: | 881 case Builtins::kObjectPrototypeIsPrototypeOf: |
| 855 return ReduceObjectPrototypeIsPrototypeOf(node); | 882 return ReduceObjectPrototypeIsPrototypeOf(node); |
| 856 case Builtins::kReflectApply: | 883 case Builtins::kReflectApply: |
| 857 return ReduceReflectApply(node); | 884 return ReduceReflectApply(node); |
| 885 case Builtins::kReflectConstruct: |
| 886 return ReduceReflectConstruct(node); |
| 858 case Builtins::kReflectGetPrototypeOf: | 887 case Builtins::kReflectGetPrototypeOf: |
| 859 return ReduceReflectGetPrototypeOf(node); | 888 return ReduceReflectGetPrototypeOf(node); |
| 860 case Builtins::kArrayForEach: | 889 case Builtins::kArrayForEach: |
| 861 return ReduceArrayForEach(function, node); | 890 return ReduceArrayForEach(function, node); |
| 862 case Builtins::kReturnReceiver: | 891 case Builtins::kReturnReceiver: |
| 863 return ReduceReturnReceiver(node); | 892 return ReduceReturnReceiver(node); |
| 864 default: | 893 default: |
| 865 break; | 894 break; |
| 866 } | 895 } |
| 867 | 896 |
| (...skipping 243 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1111 | 1140 |
| 1112 // Try to further reduce the JSConstruct {node}. | 1141 // Try to further reduce the JSConstruct {node}. |
| 1113 Reduction const reduction = ReduceJSConstruct(node); | 1142 Reduction const reduction = ReduceJSConstruct(node); |
| 1114 return reduction.Changed() ? reduction : Changed(node); | 1143 return reduction.Changed() ? reduction : Changed(node); |
| 1115 } | 1144 } |
| 1116 } | 1145 } |
| 1117 | 1146 |
| 1118 return NoChange(); | 1147 return NoChange(); |
| 1119 } | 1148 } |
| 1120 | 1149 |
| 1150 Reduction JSCallReducer::ReduceJSConstructWithArrayLike(Node* node) { |
| 1151 DCHECK_EQ(IrOpcode::kJSConstructWithArrayLike, node->opcode()); |
| 1152 CallFrequency frequency = CallFrequencyOf(node->op()); |
| 1153 return ReduceCallOrConstructWithArrayLikeOrSpread(node, 1, frequency); |
| 1154 } |
| 1155 |
| 1121 Reduction JSCallReducer::ReduceJSConstructWithSpread(Node* node) { | 1156 Reduction JSCallReducer::ReduceJSConstructWithSpread(Node* node) { |
| 1122 DCHECK_EQ(IrOpcode::kJSConstructWithSpread, node->opcode()); | 1157 DCHECK_EQ(IrOpcode::kJSConstructWithSpread, node->opcode()); |
| 1123 SpreadWithArityParameter const& p = SpreadWithArityParameterOf(node->op()); | 1158 SpreadWithArityParameter const& p = SpreadWithArityParameterOf(node->op()); |
| 1124 DCHECK_LE(3u, p.arity()); | 1159 DCHECK_LE(3u, p.arity()); |
| 1125 int arity = static_cast<int>(p.arity() - 2); | 1160 int arity = static_cast<int>(p.arity() - 2); |
| 1126 | 1161 |
| 1127 // TODO(turbofan): Collect call counts on spread call/construct and thread it | 1162 // TODO(turbofan): Collect call counts on spread call/construct and thread it |
| 1128 // through here. | 1163 // through here. |
| 1129 CallFrequency frequency; | 1164 CallFrequency frequency; |
| 1130 return ReduceCallOrConstructWithArrayLikeOrSpread(node, arity, frequency); | 1165 return ReduceCallOrConstructWithArrayLikeOrSpread(node, arity, frequency); |
| (...skipping 25 matching lines...) Expand all Loading... |
| 1156 return jsgraph()->javascript(); | 1191 return jsgraph()->javascript(); |
| 1157 } | 1192 } |
| 1158 | 1193 |
| 1159 SimplifiedOperatorBuilder* JSCallReducer::simplified() const { | 1194 SimplifiedOperatorBuilder* JSCallReducer::simplified() const { |
| 1160 return jsgraph()->simplified(); | 1195 return jsgraph()->simplified(); |
| 1161 } | 1196 } |
| 1162 | 1197 |
| 1163 } // namespace compiler | 1198 } // namespace compiler |
| 1164 } // namespace internal | 1199 } // namespace internal |
| 1165 } // namespace v8 | 1200 } // namespace v8 |
| OLD | NEW |