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 2659623002: [turbofan] Reduce CallConstructWithSpread where iteration is not observable. (Closed)
Patch Set: respond to comments from Benedikt Created 3 years, 11 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-call-reducer.h ('k') | src/compiler/pipeline.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 8dd1ce79aa298bbe6e0761edfa9bb097fbe41ed1..67e699961a9dcb20b6f9dffa9fb0a39ed3a83e90 100644
--- a/src/compiler/js-call-reducer.cc
+++ b/src/compiler/js-call-reducer.cc
@@ -6,6 +6,7 @@
#include "src/code-factory.h"
#include "src/code-stubs.h"
+#include "src/compilation-dependencies.h"
#include "src/compiler/js-graph.h"
#include "src/compiler/linkage.h"
#include "src/compiler/node-matchers.h"
@@ -21,6 +22,8 @@ Reduction JSCallReducer::Reduce(Node* node) {
switch (node->opcode()) {
case IrOpcode::kJSCallConstruct:
return ReduceJSCallConstruct(node);
+ case IrOpcode::kJSCallConstructWithSpread:
+ return ReduceJSCallConstructWithSpread(node);
case IrOpcode::kJSCallFunction:
return ReduceJSCallFunction(node);
default:
@@ -691,10 +694,85 @@ Reduction JSCallReducer::ReduceJSCallConstruct(Node* node) {
return NoChange();
}
+Reduction JSCallReducer::ReduceJSCallConstructWithSpread(Node* node) {
+ DCHECK_EQ(IrOpcode::kJSCallConstructWithSpread, node->opcode());
+ CallConstructWithSpreadParameters const& p =
+ CallConstructWithSpreadParametersOf(node->op());
+ DCHECK_LE(3u, p.arity());
+ int arity = static_cast<int>(p.arity() - 2);
+
+ // Do check to make sure we can actually avoid iteration.
+ if (!isolate()->initial_array_iterator_prototype_map()->is_stable()) {
+ return NoChange();
+ }
+
+ Node* spread = NodeProperties::GetValueInput(node, arity);
+
+ // Check if spread is an arguments object, and {node} is the only value user
+ // 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;
+ 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());
+ 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;
+ 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();
+ } else if (type == CreateArgumentsType::kRestParameter) {
+ Handle<SharedFunctionInfo> shared;
+ if (!state_info.shared_info().ToHandle(&shared)) return NoChange();
+ start_index = shared->internal_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());
+ }
+
+ dependencies()->AssumeMapStable(
+ isolate()->initial_array_iterator_prototype_map());
+
+ // Remove the spread input from the {node}.
+ node->RemoveInput(arity--);
+
+ // 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) {
+ node->InsertInput(graph()->zone(), static_cast<int>(++arity),
+ parameters->InputAt(i));
+ }
+
+ NodeProperties::ChangeOp(
+ node, javascript()->CallConstruct(arity + 2, 7, VectorSlotPair()));
+
+ return Changed(node);
+}
+
Graph* JSCallReducer::graph() const { return jsgraph()->graph(); }
Isolate* JSCallReducer::isolate() const { return jsgraph()->isolate(); }
+Factory* JSCallReducer::factory() const { return isolate()->factory(); }
+
CommonOperatorBuilder* JSCallReducer::common() const {
return jsgraph()->common();
}
« no previous file with comments | « src/compiler/js-call-reducer.h ('k') | src/compiler/pipeline.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698