Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(102)

Unified Diff: src/compiler/js-create-lowering.cc

Issue 2127713003: [TurboFan] Improve Array constructor optimization (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Test file fixes. Created 4 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/compiler/js-create-lowering.h ('k') | src/compiler/js-generic-lowering.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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) {
« no previous file with comments | « src/compiler/js-create-lowering.h ('k') | src/compiler/js-generic-lowering.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698