Index: src/compiler/js-create-lowering.cc |
diff --git a/src/compiler/js-create-lowering.cc b/src/compiler/js-create-lowering.cc |
index 5869234ec35d8b0c817de1805878a4608cdf68df..6a726b9f645b0b33e471a0d9a3392fa7b6f6906d 100644 |
--- a/src/compiler/js-create-lowering.cc |
+++ b/src/compiler/js-create-lowering.cc |
@@ -594,6 +594,66 @@ Reduction JSCreateLowering::ReduceNewArray(Node* node, Node* length, |
return Changed(node); |
} |
+Reduction JSCreateLowering::ReduceNewArray(Node* node, |
+ std::vector<Node*> values, |
+ Handle<AllocationSite> site) { |
+ DCHECK_EQ(IrOpcode::kJSCreateArray, node->opcode()); |
+ Node* effect = NodeProperties::GetEffectInput(node); |
+ Node* control = NodeProperties::GetControlInput(node); |
+ |
+ // Extract transition and tenuring feedback from the {site} and add |
+ // appropriate code dependencies on the {site} if deoptimization is |
+ // enabled. |
+ PretenureFlag pretenure = site->GetPretenureMode(); |
+ ElementsKind elements_kind = site->GetElementsKind(); |
+ DCHECK(IsFastElementsKind(elements_kind)); |
+ dependencies()->AssumeTenuringDecision(site); |
+ dependencies()->AssumeTransitionStable(site); |
+ |
+ // Check {values} based on the {elements_kind}. These checks are guarded |
+ // by the {elements_kind} feedback on the {site}, so it's safe to just |
+ // deoptimize in this case. |
+ if (IsFastSmiElementsKind(elements_kind)) { |
+ for (auto& value : values) { |
+ if (!NodeProperties::GetType(value)->Is(Type::SignedSmall())) { |
+ value = effect = |
+ graph()->NewNode(simplified()->CheckSmi(), value, effect, control); |
+ } |
+ } |
+ } else if (IsFastDoubleElementsKind(elements_kind)) { |
+ for (auto& value : values) { |
+ if (!NodeProperties::GetType(value)->Is(Type::Number())) { |
+ value = effect = graph()->NewNode(simplified()->CheckNumber(), value, |
+ effect, control); |
+ } |
+ // Make sure we do not store signaling NaNs into double arrays. |
+ value = graph()->NewNode(simplified()->NumberSilenceNaN(), value); |
+ } |
+ } |
+ |
+ // Retrieve the initial map for the array. |
+ int const array_map_index = Context::ArrayMapIndex(elements_kind); |
+ Node* js_array_map = jsgraph()->HeapConstant( |
+ handle(Map::cast(native_context()->get(array_map_index)), isolate())); |
+ |
+ // Setup elements, properties and length. |
+ Node* elements = effect = |
+ AllocateElements(effect, control, elements_kind, values, pretenure); |
+ Node* properties = jsgraph()->EmptyFixedArrayConstant(); |
+ Node* length = jsgraph()->Constant(static_cast<int>(values.size())); |
+ |
+ // Perform the allocation of the actual JSArray object. |
+ AllocationBuilder a(jsgraph(), effect, control); |
+ a.Allocate(JSArray::kSize, pretenure); |
+ a.Store(AccessBuilder::ForMap(), js_array_map); |
+ a.Store(AccessBuilder::ForJSObjectProperties(), properties); |
+ a.Store(AccessBuilder::ForJSObjectElements(), elements); |
+ a.Store(AccessBuilder::ForJSArrayLength(elements_kind), length); |
+ RelaxControls(node); |
+ a.FinishAndChange(node); |
+ return Changed(node); |
+} |
+ |
Reduction JSCreateLowering::ReduceNewArrayToStubCall( |
Node* node, Handle<AllocationSite> site) { |
CreateArrayParameters const& p = CreateArrayParametersOf(node->op()); |
@@ -755,12 +815,25 @@ Reduction JSCreateLowering::ReduceJSCreateArray(Node* node) { |
} else if (p.arity() == 1) { |
Node* length = NodeProperties::GetValueInput(node, 2); |
Type* length_type = NodeProperties::GetType(length); |
+ if (!length_type->Maybe(Type::Unsigned32())) { |
+ // Handle the single argument case, where we know that the value |
+ // cannot be a valid Array length. |
+ return ReduceNewArray(node, {length}, site); |
+ } |
if (length_type->Is(Type::SignedSmall()) && length_type->Min() >= 0 && |
length_type->Max() <= kElementLoopUnrollLimit && |
length_type->Min() == length_type->Max()) { |
int capacity = static_cast<int>(length_type->Max()); |
return ReduceNewArray(node, length, capacity, site); |
} |
+ } else if (p.arity() <= JSArray::kInitialMaxFastElementArray) { |
+ std::vector<Node*> values; |
+ values.reserve(p.arity()); |
+ for (size_t i = 0; i < p.arity(); ++i) { |
+ values.push_back( |
+ NodeProperties::GetValueInput(node, static_cast<int>(2 + i))); |
+ } |
+ return ReduceNewArray(node, values, site); |
} |
} |
@@ -1125,6 +1198,31 @@ Node* JSCreateLowering::AllocateElements(Node* effect, Node* control, |
return a.Finish(); |
} |
+Node* JSCreateLowering::AllocateElements(Node* effect, Node* control, |
+ ElementsKind elements_kind, |
+ std::vector<Node*> const& values, |
+ PretenureFlag pretenure) { |
+ int const capacity = static_cast<int>(values.size()); |
+ DCHECK_LE(1, capacity); |
+ DCHECK_LE(capacity, JSArray::kInitialMaxFastElementArray); |
+ |
+ Handle<Map> elements_map = IsFastDoubleElementsKind(elements_kind) |
+ ? factory()->fixed_double_array_map() |
+ : factory()->fixed_array_map(); |
+ ElementAccess access = IsFastDoubleElementsKind(elements_kind) |
+ ? AccessBuilder::ForFixedDoubleArrayElement() |
+ : AccessBuilder::ForFixedArrayElement(); |
+ |
+ // Actually allocate the backing store. |
+ AllocationBuilder a(jsgraph(), effect, control); |
+ a.AllocateArray(capacity, elements_map, pretenure); |
+ for (int i = 0; i < capacity; ++i) { |
+ Node* index = jsgraph()->Constant(i); |
+ a.Store(access, index, values[i]); |
+ } |
+ return a.Finish(); |
+} |
+ |
Node* JSCreateLowering::AllocateFastLiteral( |
Node* effect, Node* control, Handle<JSObject> boilerplate, |
AllocationSiteUsageContext* site_context) { |