OLD | NEW |
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/js-create-lowering.h" | 5 #include "src/compiler/js-create-lowering.h" |
6 | 6 |
7 #include "src/allocation-site-scopes.h" | 7 #include "src/allocation-site-scopes.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 576 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
587 a.Allocate(JSArray::kSize, pretenure); | 587 a.Allocate(JSArray::kSize, pretenure); |
588 a.Store(AccessBuilder::ForMap(), js_array_map); | 588 a.Store(AccessBuilder::ForMap(), js_array_map); |
589 a.Store(AccessBuilder::ForJSObjectProperties(), properties); | 589 a.Store(AccessBuilder::ForJSObjectProperties(), properties); |
590 a.Store(AccessBuilder::ForJSObjectElements(), elements); | 590 a.Store(AccessBuilder::ForJSObjectElements(), elements); |
591 a.Store(AccessBuilder::ForJSArrayLength(elements_kind), length); | 591 a.Store(AccessBuilder::ForJSArrayLength(elements_kind), length); |
592 RelaxControls(node); | 592 RelaxControls(node); |
593 a.FinishAndChange(node); | 593 a.FinishAndChange(node); |
594 return Changed(node); | 594 return Changed(node); |
595 } | 595 } |
596 | 596 |
| 597 Reduction JSCreateLowering::ReduceNewArray(Node* node, |
| 598 std::vector<Node*> values, |
| 599 Handle<AllocationSite> site) { |
| 600 DCHECK_EQ(IrOpcode::kJSCreateArray, node->opcode()); |
| 601 Node* effect = NodeProperties::GetEffectInput(node); |
| 602 Node* control = NodeProperties::GetControlInput(node); |
| 603 |
| 604 // Extract transition and tenuring feedback from the {site} and add |
| 605 // appropriate code dependencies on the {site} if deoptimization is |
| 606 // enabled. |
| 607 PretenureFlag pretenure = site->GetPretenureMode(); |
| 608 ElementsKind elements_kind = site->GetElementsKind(); |
| 609 DCHECK(IsFastElementsKind(elements_kind)); |
| 610 dependencies()->AssumeTenuringDecision(site); |
| 611 dependencies()->AssumeTransitionStable(site); |
| 612 |
| 613 // Check {values} based on the {elements_kind}. These checks are guarded |
| 614 // by the {elements_kind} feedback on the {site}, so it's safe to just |
| 615 // deoptimize in this case. |
| 616 if (IsFastSmiElementsKind(elements_kind)) { |
| 617 for (auto& value : values) { |
| 618 if (!NodeProperties::GetType(value)->Is(Type::SignedSmall())) { |
| 619 value = effect = |
| 620 graph()->NewNode(simplified()->CheckSmi(), value, effect, control); |
| 621 } |
| 622 } |
| 623 } else if (IsFastDoubleElementsKind(elements_kind)) { |
| 624 for (auto& value : values) { |
| 625 if (!NodeProperties::GetType(value)->Is(Type::Number())) { |
| 626 value = effect = graph()->NewNode(simplified()->CheckNumber(), value, |
| 627 effect, control); |
| 628 } |
| 629 // Make sure we do not store signaling NaNs into double arrays. |
| 630 value = graph()->NewNode(simplified()->NumberSilenceNaN(), value); |
| 631 } |
| 632 } |
| 633 |
| 634 // Retrieve the initial map for the array. |
| 635 int const array_map_index = Context::ArrayMapIndex(elements_kind); |
| 636 Node* js_array_map = jsgraph()->HeapConstant( |
| 637 handle(Map::cast(native_context()->get(array_map_index)), isolate())); |
| 638 |
| 639 // Setup elements, properties and length. |
| 640 Node* elements = effect = |
| 641 AllocateElements(effect, control, elements_kind, values, pretenure); |
| 642 Node* properties = jsgraph()->EmptyFixedArrayConstant(); |
| 643 Node* length = jsgraph()->Constant(static_cast<int>(values.size())); |
| 644 |
| 645 // Perform the allocation of the actual JSArray object. |
| 646 AllocationBuilder a(jsgraph(), effect, control); |
| 647 a.Allocate(JSArray::kSize, pretenure); |
| 648 a.Store(AccessBuilder::ForMap(), js_array_map); |
| 649 a.Store(AccessBuilder::ForJSObjectProperties(), properties); |
| 650 a.Store(AccessBuilder::ForJSObjectElements(), elements); |
| 651 a.Store(AccessBuilder::ForJSArrayLength(elements_kind), length); |
| 652 RelaxControls(node); |
| 653 a.FinishAndChange(node); |
| 654 return Changed(node); |
| 655 } |
| 656 |
597 Reduction JSCreateLowering::ReduceNewArrayToStubCall( | 657 Reduction JSCreateLowering::ReduceNewArrayToStubCall( |
598 Node* node, Handle<AllocationSite> site) { | 658 Node* node, Handle<AllocationSite> site) { |
599 CreateArrayParameters const& p = CreateArrayParametersOf(node->op()); | 659 CreateArrayParameters const& p = CreateArrayParametersOf(node->op()); |
600 int const arity = static_cast<int>(p.arity()); | 660 int const arity = static_cast<int>(p.arity()); |
601 Node* target = NodeProperties::GetValueInput(node, 0); | 661 Node* target = NodeProperties::GetValueInput(node, 0); |
602 Node* new_target = NodeProperties::GetValueInput(node, 1); | 662 Node* new_target = NodeProperties::GetValueInput(node, 1); |
603 Type* new_target_type = NodeProperties::GetType(new_target); | 663 Type* new_target_type = NodeProperties::GetType(new_target); |
604 | 664 |
605 ElementsKind elements_kind = site->GetElementsKind(); | 665 ElementsKind elements_kind = site->GetElementsKind(); |
606 AllocationSiteOverrideMode override_mode = | 666 AllocationSiteOverrideMode override_mode = |
(...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
748 // where either no arguments are provided, or exactly one unsigned number | 808 // where either no arguments are provided, or exactly one unsigned number |
749 // argument is given. | 809 // argument is given. |
750 if (site->CanInlineCall()) { | 810 if (site->CanInlineCall()) { |
751 if (p.arity() == 0) { | 811 if (p.arity() == 0) { |
752 Node* length = jsgraph()->ZeroConstant(); | 812 Node* length = jsgraph()->ZeroConstant(); |
753 int capacity = JSArray::kPreallocatedArrayElements; | 813 int capacity = JSArray::kPreallocatedArrayElements; |
754 return ReduceNewArray(node, length, capacity, site); | 814 return ReduceNewArray(node, length, capacity, site); |
755 } else if (p.arity() == 1) { | 815 } else if (p.arity() == 1) { |
756 Node* length = NodeProperties::GetValueInput(node, 2); | 816 Node* length = NodeProperties::GetValueInput(node, 2); |
757 Type* length_type = NodeProperties::GetType(length); | 817 Type* length_type = NodeProperties::GetType(length); |
| 818 if (!length_type->Maybe(Type::Unsigned32())) { |
| 819 // Handle the single argument case, where we know that the value |
| 820 // cannot be a valid Array length. |
| 821 return ReduceNewArray(node, {length}, site); |
| 822 } |
758 if (length_type->Is(Type::SignedSmall()) && length_type->Min() >= 0 && | 823 if (length_type->Is(Type::SignedSmall()) && length_type->Min() >= 0 && |
759 length_type->Max() <= kElementLoopUnrollLimit && | 824 length_type->Max() <= kElementLoopUnrollLimit && |
760 length_type->Min() == length_type->Max()) { | 825 length_type->Min() == length_type->Max()) { |
761 int capacity = static_cast<int>(length_type->Max()); | 826 int capacity = static_cast<int>(length_type->Max()); |
762 return ReduceNewArray(node, length, capacity, site); | 827 return ReduceNewArray(node, length, capacity, site); |
763 } | 828 } |
| 829 } else if (p.arity() <= JSArray::kInitialMaxFastElementArray) { |
| 830 std::vector<Node*> values; |
| 831 values.reserve(p.arity()); |
| 832 for (size_t i = 0; i < p.arity(); ++i) { |
| 833 values.push_back( |
| 834 NodeProperties::GetValueInput(node, static_cast<int>(2 + i))); |
| 835 } |
| 836 return ReduceNewArray(node, values, site); |
764 } | 837 } |
765 } | 838 } |
766 | 839 |
767 return ReduceNewArrayToStubCall(node, site); | 840 return ReduceNewArrayToStubCall(node, site); |
768 } | 841 } |
769 | 842 |
770 Reduction JSCreateLowering::ReduceJSCreateIterResultObject(Node* node) { | 843 Reduction JSCreateLowering::ReduceJSCreateIterResultObject(Node* node) { |
771 DCHECK_EQ(IrOpcode::kJSCreateIterResultObject, node->opcode()); | 844 DCHECK_EQ(IrOpcode::kJSCreateIterResultObject, node->opcode()); |
772 Node* value = NodeProperties::GetValueInput(node, 0); | 845 Node* value = NodeProperties::GetValueInput(node, 0); |
773 Node* done = NodeProperties::GetValueInput(node, 1); | 846 Node* done = NodeProperties::GetValueInput(node, 1); |
(...skipping 344 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1118 // Actually allocate the backing store. | 1191 // Actually allocate the backing store. |
1119 AllocationBuilder a(jsgraph(), effect, control); | 1192 AllocationBuilder a(jsgraph(), effect, control); |
1120 a.AllocateArray(capacity, elements_map, pretenure); | 1193 a.AllocateArray(capacity, elements_map, pretenure); |
1121 for (int i = 0; i < capacity; ++i) { | 1194 for (int i = 0; i < capacity; ++i) { |
1122 Node* index = jsgraph()->Constant(i); | 1195 Node* index = jsgraph()->Constant(i); |
1123 a.Store(access, index, value); | 1196 a.Store(access, index, value); |
1124 } | 1197 } |
1125 return a.Finish(); | 1198 return a.Finish(); |
1126 } | 1199 } |
1127 | 1200 |
| 1201 Node* JSCreateLowering::AllocateElements(Node* effect, Node* control, |
| 1202 ElementsKind elements_kind, |
| 1203 std::vector<Node*> const& values, |
| 1204 PretenureFlag pretenure) { |
| 1205 int const capacity = static_cast<int>(values.size()); |
| 1206 DCHECK_LE(1, capacity); |
| 1207 DCHECK_LE(capacity, JSArray::kInitialMaxFastElementArray); |
| 1208 |
| 1209 Handle<Map> elements_map = IsFastDoubleElementsKind(elements_kind) |
| 1210 ? factory()->fixed_double_array_map() |
| 1211 : factory()->fixed_array_map(); |
| 1212 ElementAccess access = IsFastDoubleElementsKind(elements_kind) |
| 1213 ? AccessBuilder::ForFixedDoubleArrayElement() |
| 1214 : AccessBuilder::ForFixedArrayElement(); |
| 1215 |
| 1216 // Actually allocate the backing store. |
| 1217 AllocationBuilder a(jsgraph(), effect, control); |
| 1218 a.AllocateArray(capacity, elements_map, pretenure); |
| 1219 for (int i = 0; i < capacity; ++i) { |
| 1220 Node* index = jsgraph()->Constant(i); |
| 1221 a.Store(access, index, values[i]); |
| 1222 } |
| 1223 return a.Finish(); |
| 1224 } |
| 1225 |
1128 Node* JSCreateLowering::AllocateFastLiteral( | 1226 Node* JSCreateLowering::AllocateFastLiteral( |
1129 Node* effect, Node* control, Handle<JSObject> boilerplate, | 1227 Node* effect, Node* control, Handle<JSObject> boilerplate, |
1130 AllocationSiteUsageContext* site_context) { | 1228 AllocationSiteUsageContext* site_context) { |
1131 Handle<AllocationSite> current_site(*site_context->current(), isolate()); | 1229 Handle<AllocationSite> current_site(*site_context->current(), isolate()); |
1132 dependencies()->AssumeTransitionStable(current_site); | 1230 dependencies()->AssumeTransitionStable(current_site); |
1133 | 1231 |
1134 PretenureFlag pretenure = NOT_TENURED; | 1232 PretenureFlag pretenure = NOT_TENURED; |
1135 if (FLAG_allocation_site_pretenuring) { | 1233 if (FLAG_allocation_site_pretenuring) { |
1136 Handle<AllocationSite> top_site(*site_context->top(), isolate()); | 1234 Handle<AllocationSite> top_site(*site_context->top(), isolate()); |
1137 pretenure = top_site->GetPretenureMode(); | 1235 pretenure = top_site->GetPretenureMode(); |
(...skipping 207 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1345 return jsgraph()->simplified(); | 1443 return jsgraph()->simplified(); |
1346 } | 1444 } |
1347 | 1445 |
1348 MachineOperatorBuilder* JSCreateLowering::machine() const { | 1446 MachineOperatorBuilder* JSCreateLowering::machine() const { |
1349 return jsgraph()->machine(); | 1447 return jsgraph()->machine(); |
1350 } | 1448 } |
1351 | 1449 |
1352 } // namespace compiler | 1450 } // namespace compiler |
1353 } // namespace internal | 1451 } // namespace internal |
1354 } // namespace v8 | 1452 } // namespace v8 |
OLD | NEW |