| 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) {
|
|
|