Index: src/compiler/js-create-lowering.cc |
diff --git a/src/compiler/js-create-lowering.cc b/src/compiler/js-create-lowering.cc |
index 0f829d48aefad7d38583813afe60eb108ce7396b..525b5c530cbfd633a687f057b56f1087b79443d8 100644 |
--- a/src/compiler/js-create-lowering.cc |
+++ b/src/compiler/js-create-lowering.cc |
@@ -509,12 +509,144 @@ Reduction JSCreateLowering::ReduceNewArray(Node* node, Node* length, |
return Changed(node); |
} |
+Reduction JSCreateLowering::ReduceNewArrayToStubCall( |
+ Node* node, Handle<AllocationSite> site) { |
+ CreateArrayParameters const& p = CreateArrayParametersOf(node->op()); |
+ int const arity = static_cast<int>(p.arity()); |
+ |
+ ElementsKind elements_kind = site->GetElementsKind(); |
+ AllocationSiteOverrideMode override_mode = |
+ (AllocationSite::GetMode(elements_kind) == TRACK_ALLOCATION_SITE) |
+ ? DISABLE_ALLOCATION_SITES |
+ : DONT_OVERRIDE; |
+ |
+ if (arity == 0) { |
+ ArrayNoArgumentConstructorStub stub(isolate(), elements_kind, |
+ override_mode); |
+ CallDescriptor* desc = Linkage::GetStubCallDescriptor( |
+ isolate(), graph()->zone(), stub.GetCallInterfaceDescriptor(), 1, |
+ CallDescriptor::kNeedsFrameState); |
+ node->ReplaceInput(0, jsgraph()->HeapConstant(stub.GetCode())); |
+ node->InsertInput(graph()->zone(), 2, jsgraph()->HeapConstant(site)); |
+ node->InsertInput(graph()->zone(), 3, jsgraph()->Int32Constant(0)); |
+ node->InsertInput(graph()->zone(), 4, jsgraph()->UndefinedConstant()); |
+ NodeProperties::ChangeOp(node, common()->Call(desc)); |
+ return Changed(node); |
+ } else if (arity == 1) { |
+ AllocationSiteOverrideMode override_mode = |
+ (AllocationSite::GetMode(elements_kind) == TRACK_ALLOCATION_SITE) |
+ ? DISABLE_ALLOCATION_SITES |
+ : DONT_OVERRIDE; |
+ |
+ if (IsHoleyElementsKind(elements_kind)) { |
+ ArraySingleArgumentConstructorStub stub(isolate(), elements_kind, |
+ override_mode); |
+ CallDescriptor* desc = Linkage::GetStubCallDescriptor( |
+ isolate(), graph()->zone(), stub.GetCallInterfaceDescriptor(), 2, |
+ CallDescriptor::kNeedsFrameState); |
+ node->ReplaceInput(0, jsgraph()->HeapConstant(stub.GetCode())); |
+ node->InsertInput(graph()->zone(), 2, jsgraph()->HeapConstant(site)); |
+ node->InsertInput(graph()->zone(), 3, jsgraph()->Int32Constant(1)); |
+ node->InsertInput(graph()->zone(), 4, jsgraph()->UndefinedConstant()); |
+ NodeProperties::ChangeOp(node, common()->Call(desc)); |
+ return Changed(node); |
+ } |
+ |
+ Node* effect = NodeProperties::GetEffectInput(node); |
+ Node* control = NodeProperties::GetControlInput(node); |
+ Node* length = NodeProperties::GetValueInput(node, 2); |
+ Node* equal = graph()->NewNode(simplified()->ReferenceEqual(Type::Any()), |
+ length, jsgraph()->ZeroConstant()); |
+ |
+ Node* branch = |
+ graph()->NewNode(common()->Branch(BranchHint::kFalse), equal, control); |
+ Node* call_holey; |
+ Node* call_packed; |
+ Node* if_success_packed; |
+ Node* if_success_holey; |
+ Node* context = NodeProperties::GetContextInput(node); |
+ Node* frame_state = NodeProperties::GetFrameStateInput(node, 0); |
+ Node* if_equal = graph()->NewNode(common()->IfTrue(), branch); |
+ { |
+ ArraySingleArgumentConstructorStub stub(isolate(), elements_kind, |
+ override_mode); |
+ CallDescriptor* desc = Linkage::GetStubCallDescriptor( |
+ isolate(), graph()->zone(), stub.GetCallInterfaceDescriptor(), 2, |
+ CallDescriptor::kNeedsFrameState); |
+ |
+ Node* inputs[] = {jsgraph()->HeapConstant(stub.GetCode()), |
+ node->InputAt(1), |
+ jsgraph()->HeapConstant(site), |
+ jsgraph()->Int32Constant(1), |
+ jsgraph()->UndefinedConstant(), |
+ length, |
+ context, |
+ frame_state, |
+ effect, |
+ if_equal}; |
+ |
+ call_holey = |
+ graph()->NewNode(common()->Call(desc), arraysize(inputs), inputs); |
+ if_success_holey = graph()->NewNode(common()->IfSuccess(), call_holey); |
+ } |
+ Node* if_not_equal = graph()->NewNode(common()->IfFalse(), branch); |
+ { |
+ // Require elements kind to "go holey." |
+ ArraySingleArgumentConstructorStub stub( |
+ isolate(), GetHoleyElementsKind(elements_kind), override_mode); |
+ CallDescriptor* desc = Linkage::GetStubCallDescriptor( |
+ isolate(), graph()->zone(), stub.GetCallInterfaceDescriptor(), 2, |
+ CallDescriptor::kNeedsFrameState); |
+ |
+ Node* inputs[] = {jsgraph()->HeapConstant(stub.GetCode()), |
+ node->InputAt(1), |
+ jsgraph()->HeapConstant(site), |
+ jsgraph()->Int32Constant(1), |
+ jsgraph()->UndefinedConstant(), |
+ length, |
+ context, |
+ frame_state, |
+ effect, |
+ if_not_equal}; |
+ |
+ call_packed = |
+ graph()->NewNode(common()->Call(desc), arraysize(inputs), inputs); |
+ if_success_packed = graph()->NewNode(common()->IfSuccess(), call_packed); |
+ } |
+ Node* merge = graph()->NewNode(common()->Merge(2), if_success_holey, |
+ if_success_packed); |
+ Node* effect_phi = graph()->NewNode(common()->EffectPhi(2), call_holey, |
+ call_packed, merge); |
+ Node* phi = |
+ graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2), |
+ call_holey, call_packed, merge); |
+ |
+ ReplaceWithValue(node, phi, effect_phi, merge); |
+ return Changed(node); |
+ } |
+ |
+ DCHECK(arity > 1); |
+ ArrayNArgumentsConstructorStub stub(isolate()); |
+ CallDescriptor* desc = Linkage::GetStubCallDescriptor( |
+ isolate(), graph()->zone(), stub.GetCallInterfaceDescriptor(), arity + 1, |
+ CallDescriptor::kNeedsFrameState); |
+ node->ReplaceInput(0, jsgraph()->HeapConstant(stub.GetCode())); |
+ node->InsertInput(graph()->zone(), 2, jsgraph()->HeapConstant(site)); |
+ node->InsertInput(graph()->zone(), 3, jsgraph()->Int32Constant(arity)); |
+ node->InsertInput(graph()->zone(), 4, jsgraph()->UndefinedConstant()); |
+ NodeProperties::ChangeOp(node, common()->Call(desc)); |
+ return Changed(node); |
+} |
+ |
Reduction JSCreateLowering::ReduceJSCreateArray(Node* node) { |
DCHECK_EQ(IrOpcode::kJSCreateArray, node->opcode()); |
CreateArrayParameters const& p = CreateArrayParametersOf(node->op()); |
Node* target = NodeProperties::GetValueInput(node, 0); |
Node* new_target = NodeProperties::GetValueInput(node, 1); |
+ // TODO(mstarzinger): Array constructor can throw. Hook up exceptional edges. |
+ if (NodeProperties::IsExceptionalCall(node)) return NoChange(); |
+ |
// TODO(bmeurer): Optimize the subclassing case. |
if (target != new_target) return NoChange(); |
@@ -533,16 +665,16 @@ 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->Is(Type::SignedSmall()) && |
- length_type->Min() >= 0 && |
- length_type->Max() <= kElementLoopUnrollLimit) { |
+ 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); |
} |
} |
} |
- return NoChange(); |
+ return ReduceNewArrayToStubCall(node, site); |
} |
Reduction JSCreateLowering::ReduceJSCreateClosure(Node* node) { |