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

Unified Diff: src/compiler/js-call-reducer.cc

Issue 2890023004: [turbofan] Avoid allocating rest parameters for spread calls. (Closed)
Patch Set: Created 3 years, 7 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/code-factory.cc ('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-call-reducer.cc
diff --git a/src/compiler/js-call-reducer.cc b/src/compiler/js-call-reducer.cc
index dfade082168a1594e1211610fe455adbb10ce354..1e1d3a92ab01abc235b58dbec165db4ad3d83ecb 100644
--- a/src/compiler/js-call-reducer.cc
+++ b/src/compiler/js-call-reducer.cc
@@ -124,7 +124,8 @@ Reduction JSCallReducer::ReduceFunctionPrototypeApply(Node* node) {
Node* arg_array = NodeProperties::GetValueInput(node, 3);
if (arg_array->opcode() != IrOpcode::kJSCreateArguments) return NoChange();
for (Edge edge : arg_array->use_edges()) {
- Node* user = edge.from();
+ Node* const user = edge.from();
+ if (user == node) continue;
// Ignore uses as frame state's locals or parameters.
if (user->opcode() == IrOpcode::kStateValues) continue;
// Ignore uses as frame state's accumulator.
@@ -133,7 +134,6 @@ Reduction JSCallReducer::ReduceFunctionPrototypeApply(Node* node) {
continue;
}
if (!NodeProperties::IsValueEdge(edge)) continue;
- if (edge.from() == node) continue;
return NoChange();
}
// Check if the arguments can be handled in the fast case (i.e. we don't
@@ -173,7 +173,7 @@ Reduction JSCallReducer::ReduceFunctionPrototypeApply(Node* node) {
node->RemoveInput(0); // Function.prototype.apply
node->RemoveInput(2); // arguments
NodeProperties::ChangeOp(node, javascript()->CallForwardVarargs(
- start_index, p.tail_call_mode()));
+ 2, start_index, p.tail_call_mode()));
return Changed(node);
}
// Get to the actual frame state from which to extract the arguments;
@@ -454,50 +454,81 @@ Reduction JSCallReducer::ReduceSpreadCall(Node* node, int arity) {
// of spread (except for value uses in frame states).
if (spread->opcode() != IrOpcode::kJSCreateArguments) return NoChange();
for (Edge edge : spread->use_edges()) {
- if (edge.from()->opcode() == IrOpcode::kStateValues) continue;
+ Node* const user = edge.from();
+ if (user == node) continue;
+ // Ignore uses as frame state's locals or parameters.
+ if (user->opcode() == IrOpcode::kStateValues) continue;
+ // Ignore uses as frame state's accumulator.
+ if (user->opcode() == IrOpcode::kFrameState && user->InputAt(2) == spread) {
+ continue;
+ }
if (!NodeProperties::IsValueEdge(edge)) continue;
- if (edge.from() == node) continue;
return NoChange();
}
// Get to the actual frame state from which to extract the arguments;
// we can only optimize this in case the {node} was already inlined into
// some other function (and same for the {spread}).
- CreateArgumentsType type = CreateArgumentsTypeOf(spread->op());
+ CreateArgumentsType const type = CreateArgumentsTypeOf(spread->op());
Node* frame_state = NodeProperties::GetFrameStateInput(spread);
- Node* outer_state = frame_state->InputAt(kFrameStateOuterStateInput);
- if (outer_state->opcode() != IrOpcode::kFrameState) return NoChange();
- FrameStateInfo outer_info = OpParameter<FrameStateInfo>(outer_state);
- if (outer_info.type() == FrameStateType::kArgumentsAdaptor) {
- // Need to take the parameters from the arguments adaptor.
- frame_state = outer_state;
- }
FrameStateInfo state_info = OpParameter<FrameStateInfo>(frame_state);
int start_index = 0;
+ // Determine the formal parameter count;
+ Handle<SharedFunctionInfo> shared;
+ if (!state_info.shared_info().ToHandle(&shared)) return NoChange();
+ int formal_parameter_count = shared->internal_formal_parameter_count();
if (type == CreateArgumentsType::kMappedArguments) {
- // Mapped arguments (sloppy mode) cannot be handled if they are aliased.
- Handle<SharedFunctionInfo> shared;
- if (!state_info.shared_info().ToHandle(&shared)) return NoChange();
- if (shared->internal_formal_parameter_count() != 0) return NoChange();
+ // Mapped arguments (sloppy mode) that are aliased can only be handled
+ // here if there's no side-effect between the {node} and the {arg_array}.
+ // TODO(turbofan): Further relax this constraint.
+ if (formal_parameter_count != 0) {
+ Node* effect = NodeProperties::GetEffectInput(node);
+ while (effect != spread) {
+ if (effect->op()->EffectInputCount() != 1 ||
+ !(effect->op()->properties() & Operator::kNoWrite)) {
+ return NoChange();
+ }
+ effect = NodeProperties::GetEffectInput(effect);
+ }
+ }
} else if (type == CreateArgumentsType::kRestParameter) {
- Handle<SharedFunctionInfo> shared;
- if (!state_info.shared_info().ToHandle(&shared)) return NoChange();
- start_index = shared->internal_formal_parameter_count();
+ start_index = formal_parameter_count;
// Only check the array iterator protector when we have a rest object.
if (!isolate()->IsArrayIteratorLookupChainIntact()) return NoChange();
- // Add a code dependency on the array iterator protector.
- dependencies()->AssumePropertyCell(factory()->array_iterator_protector());
}
+ // Install appropriate code dependencies.
dependencies()->AssumeMapStable(
isolate()->initial_array_iterator_prototype_map());
-
+ if (type == CreateArgumentsType::kRestParameter) {
+ dependencies()->AssumePropertyCell(factory()->array_iterator_protector());
+ }
+ // Remove the spread input from the {node}.
node->RemoveInput(arity--);
-
+ // Check if are spreading to inlined arguments or to the arguments of
+ // the outermost function.
+ Node* outer_state = frame_state->InputAt(kFrameStateOuterStateInput);
+ if (outer_state->opcode() != IrOpcode::kFrameState) {
+ Operator const* op =
+ (node->opcode() == IrOpcode::kJSCallWithSpread)
+ ? javascript()->CallForwardVarargs(arity + 1, start_index,
+ TailCallMode::kDisallow)
+ : javascript()->ConstructForwardVarargs(arity + 2, start_index);
+ NodeProperties::ChangeOp(node, op);
+ return Changed(node);
+ }
+ // Get to the actual frame state from which to extract the arguments;
+ // we can only optimize this in case the {node} was already inlined into
+ // some other function (and same for the {arg_array}).
+ FrameStateInfo outer_info = OpParameter<FrameStateInfo>(outer_state);
+ if (outer_info.type() == FrameStateType::kArgumentsAdaptor) {
+ // Need to take the parameters from the arguments adaptor.
+ frame_state = outer_state;
+ }
// Add the actual parameters to the {node}, skipping the receiver.
Node* const parameters = frame_state->InputAt(kFrameStateParametersInput);
- for (int i = start_index + 1; i < state_info.parameter_count(); ++i) {
+ for (int i = start_index + 1; i < parameters->InputCount(); ++i) {
node->InsertInput(graph()->zone(), static_cast<int>(++arity),
parameters->InputAt(i));
}
« no previous file with comments | « src/code-factory.cc ('k') | src/compiler/js-generic-lowering.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698