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

Side by Side Diff: src/compiler/js-call-reducer.cc

Issue 1451273002: [turbofan] Move JSCallFunction specialization to JSCallReducer. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Fix arm64 failures. Created 5 years, 1 month 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 unified diff | Download patch
« no previous file with comments | « src/compiler/js-call-reducer.h ('k') | src/compiler/js-native-context-specialization.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2015 the V8 project authors. All rights reserved. 1 // Copyright 2015 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "src/compiler/js-call-reducer.h" 5 #include "src/compiler/js-call-reducer.h"
6 6
7 #include "src/compiler/js-graph.h" 7 #include "src/compiler/js-graph.h"
8 #include "src/compiler/node-matchers.h" 8 #include "src/compiler/node-matchers.h"
9 #include "src/compiler/simplified-operator.h"
9 #include "src/objects-inl.h" 10 #include "src/objects-inl.h"
10 #include "src/type-feedback-vector-inl.h" 11 #include "src/type-feedback-vector-inl.h"
11 12
12 namespace v8 { 13 namespace v8 {
13 namespace internal { 14 namespace internal {
14 namespace compiler { 15 namespace compiler {
15 16
16 namespace { 17 namespace {
17 18
18 VectorSlotPair CallCountFeedback(VectorSlotPair p) { 19 VectorSlotPair CallCountFeedback(VectorSlotPair p) {
(...skipping 12 matching lines...) Expand all
31 TypeFeedbackVector::New(n.GetIsolate(), metadata); 32 TypeFeedbackVector::New(n.GetIsolate(), metadata);
32 CallICNexus nexus(vector, slot); 33 CallICNexus nexus(vector, slot);
33 nexus.ConfigureMegamorphic(call_count); 34 nexus.ConfigureMegamorphic(call_count);
34 return VectorSlotPair(vector, slot); 35 return VectorSlotPair(vector, slot);
35 } 36 }
36 37
37 } // namespace 38 } // namespace
38 39
39 40
40 Reduction JSCallReducer::Reduce(Node* node) { 41 Reduction JSCallReducer::Reduce(Node* node) {
41 if (node->opcode() == IrOpcode::kJSCallFunction) { 42 switch (node->opcode()) {
42 HeapObjectMatcher m(node->InputAt(0)); 43 case IrOpcode::kJSCallFunction:
43 if (m.HasValue() && m.Value()->IsJSFunction()) { 44 return ReduceJSCallFunction(node);
44 Handle<SharedFunctionInfo> shared( 45 default:
45 Handle<JSFunction>::cast(m.Value())->shared(), isolate()); 46 break;
46 if (shared->HasBuiltinFunctionId()) {
47 switch (shared->builtin_function_id()) {
48 case kFunctionApply:
49 return ReduceFunctionPrototypeApply(node);
50 case kFunctionCall:
51 return ReduceFunctionPrototypeCall(node);
52 default:
53 break;
54 }
55 }
56 }
57 } 47 }
58 return NoChange(); 48 return NoChange();
59 } 49 }
60 50
61 51
62 // ES6 section 19.2.3.1 Function.prototype.apply ( thisArg, argArray ) 52 // ES6 section 19.2.3.1 Function.prototype.apply ( thisArg, argArray )
63 Reduction JSCallReducer::ReduceFunctionPrototypeApply(Node* node) { 53 Reduction JSCallReducer::ReduceFunctionPrototypeApply(Node* node) {
64 DCHECK_EQ(IrOpcode::kJSCallFunction, node->opcode()); 54 DCHECK_EQ(IrOpcode::kJSCallFunction, node->opcode());
65 Node* target = NodeProperties::GetValueInput(node, 0); 55 Node* target = NodeProperties::GetValueInput(node, 0);
66 CallFunctionParameters const& p = CallFunctionParametersOf(node->op()); 56 CallFunctionParameters const& p = CallFunctionParametersOf(node->op());
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
126 } 116 }
127 // Change {node} to the new {JSCallFunction} operator. 117 // Change {node} to the new {JSCallFunction} operator.
128 NodeProperties::ChangeOp( 118 NodeProperties::ChangeOp(
129 node, javascript()->CallFunction(arity, p.language_mode(), 119 node, javascript()->CallFunction(arity, p.language_mode(),
130 CallCountFeedback(p.feedback()), 120 CallCountFeedback(p.feedback()),
131 convert_mode, p.tail_call_mode())); 121 convert_mode, p.tail_call_mode()));
132 // Change context of {node} to the Function.prototype.apply context, 122 // Change context of {node} to the Function.prototype.apply context,
133 // to ensure any exception is thrown in the correct context. 123 // to ensure any exception is thrown in the correct context.
134 NodeProperties::ReplaceContextInput( 124 NodeProperties::ReplaceContextInput(
135 node, jsgraph()->HeapConstant(handle(apply->context(), isolate()))); 125 node, jsgraph()->HeapConstant(handle(apply->context(), isolate())));
136 return Changed(node); 126 // Try to further reduce the JSCallFunction {node}.
127 Reduction const reduction = ReduceJSCallFunction(node);
128 return reduction.Changed() ? reduction : Changed(node);
137 } 129 }
138 130
139 131
140 // ES6 section 19.2.3.3 Function.prototype.call (thisArg, ...args) 132 // ES6 section 19.2.3.3 Function.prototype.call (thisArg, ...args)
141 Reduction JSCallReducer::ReduceFunctionPrototypeCall(Node* node) { 133 Reduction JSCallReducer::ReduceFunctionPrototypeCall(Node* node) {
142 DCHECK_EQ(IrOpcode::kJSCallFunction, node->opcode()); 134 DCHECK_EQ(IrOpcode::kJSCallFunction, node->opcode());
143 CallFunctionParameters const& p = CallFunctionParametersOf(node->op()); 135 CallFunctionParameters const& p = CallFunctionParametersOf(node->op());
144 Handle<JSFunction> call = Handle<JSFunction>::cast( 136 Handle<JSFunction> call = Handle<JSFunction>::cast(
145 HeapObjectMatcher(NodeProperties::GetValueInput(node, 0)).Value()); 137 HeapObjectMatcher(NodeProperties::GetValueInput(node, 0)).Value());
146 // Change context of {node} to the Function.prototype.call context, 138 // Change context of {node} to the Function.prototype.call context,
(...skipping 14 matching lines...) Expand all
161 } else { 153 } else {
162 // Just remove the target, which is the first value input. 154 // Just remove the target, which is the first value input.
163 convert_mode = ConvertReceiverMode::kAny; 155 convert_mode = ConvertReceiverMode::kAny;
164 node->RemoveInput(0); 156 node->RemoveInput(0);
165 --arity; 157 --arity;
166 } 158 }
167 NodeProperties::ChangeOp( 159 NodeProperties::ChangeOp(
168 node, javascript()->CallFunction(arity, p.language_mode(), 160 node, javascript()->CallFunction(arity, p.language_mode(),
169 CallCountFeedback(p.feedback()), 161 CallCountFeedback(p.feedback()),
170 convert_mode, p.tail_call_mode())); 162 convert_mode, p.tail_call_mode()));
171 return Changed(node); 163 // Try to further reduce the JSCallFunction {node}.
164 Reduction const reduction = ReduceJSCallFunction(node);
165 return reduction.Changed() ? reduction : Changed(node);
172 } 166 }
173 167
174 168
169 Reduction JSCallReducer::ReduceJSCallFunction(Node* node) {
170 DCHECK_EQ(IrOpcode::kJSCallFunction, node->opcode());
171 CallFunctionParameters const& p = CallFunctionParametersOf(node->op());
172 Node* target = NodeProperties::GetValueInput(node, 0);
173 Node* frame_state = NodeProperties::GetFrameStateInput(node, 1);
174 Node* control = NodeProperties::GetControlInput(node);
175 Node* effect = NodeProperties::GetEffectInput(node);
176
177 // Try to specialize JSCallFunction {node}s with constant {target}s.
178 HeapObjectMatcher m(target);
179 if (m.HasValue()) {
180 if (m.Value()->IsJSFunction()) {
181 Handle<SharedFunctionInfo> shared(
182 Handle<JSFunction>::cast(m.Value())->shared(), isolate());
183
184 // Raise a TypeError if the {target} is a "classConstructor".
185 if (IsClassConstructor(shared->kind())) {
186 NodeProperties::RemoveFrameStateInput(node, 0);
187 NodeProperties::RemoveValueInputs(node);
188 NodeProperties::ChangeOp(
189 node, javascript()->CallRuntime(
190 Runtime::kThrowConstructorNonCallableError, 0));
191 return Changed(node);
192 }
193
194 // Check for known builtin functions.
195 if (shared->HasBuiltinFunctionId()) {
196 switch (shared->builtin_function_id()) {
197 case kFunctionApply:
198 return ReduceFunctionPrototypeApply(node);
199 case kFunctionCall:
200 return ReduceFunctionPrototypeCall(node);
201 default:
202 break;
203 }
204 }
205 }
206 // Don't mess with other {node}s that have a constant {target}.
207 // TODO(bmeurer): Also support optimizing bound functions and proxies here.
208 return NoChange();
209 }
210
211 // Not much we can do if deoptimization support is disabled.
212 if (!(flags() & kDeoptimizationEnabled)) return NoChange();
213
214 // Extract feedback from the {node} using the CallICNexus.
215 if (!p.feedback().IsValid()) return NoChange();
216 CallICNexus nexus(p.feedback().vector(), p.feedback().slot());
217 Handle<Object> feedback(nexus.GetFeedback(), isolate());
218 if (feedback->IsWeakCell()) {
219 Handle<WeakCell> cell = Handle<WeakCell>::cast(feedback);
220 if (cell->value()->IsJSFunction()) {
221 // Check that the {target} is still the {target_function}.
222 Node* target_function = jsgraph()->HeapConstant(
223 handle(JSFunction::cast(cell->value()), isolate()));
224 Node* check = graph()->NewNode(simplified()->ReferenceEqual(Type::Any()),
225 target, target_function);
226 Node* branch =
227 graph()->NewNode(common()->Branch(BranchHint::kTrue), check, control);
228 Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
229 Node* deoptimize = graph()->NewNode(common()->Deoptimize(), frame_state,
230 effect, if_false);
231 // TODO(bmeurer): This should be on the AdvancedReducer somehow.
232 NodeProperties::MergeControlToEnd(graph(), common(), deoptimize);
233 control = graph()->NewNode(common()->IfTrue(), branch);
234
235 // Specialize the JSCallFunction node to the {target_function}.
236 NodeProperties::ReplaceValueInput(node, target_function, 0);
237 NodeProperties::ReplaceControlInput(node, control);
238
239 // Try to further reduce the JSCallFunction {node}.
240 Reduction const reduction = ReduceJSCallFunction(node);
241 return reduction.Changed() ? reduction : Changed(node);
242 }
243 }
244 return NoChange();
245 }
246
247
175 Graph* JSCallReducer::graph() const { return jsgraph()->graph(); } 248 Graph* JSCallReducer::graph() const { return jsgraph()->graph(); }
176 249
177 250
178 Isolate* JSCallReducer::isolate() const { return jsgraph()->isolate(); } 251 Isolate* JSCallReducer::isolate() const { return jsgraph()->isolate(); }
179 252
180 253
254 CommonOperatorBuilder* JSCallReducer::common() const {
255 return jsgraph()->common();
256 }
257
258
181 JSOperatorBuilder* JSCallReducer::javascript() const { 259 JSOperatorBuilder* JSCallReducer::javascript() const {
182 return jsgraph()->javascript(); 260 return jsgraph()->javascript();
183 } 261 }
184 262
263
264 SimplifiedOperatorBuilder* JSCallReducer::simplified() const {
265 return jsgraph()->simplified();
266 }
267
185 } // namespace compiler 268 } // namespace compiler
186 } // namespace internal 269 } // namespace internal
187 } // namespace v8 270 } // namespace v8
OLDNEW
« no previous file with comments | « src/compiler/js-call-reducer.h ('k') | src/compiler/js-native-context-specialization.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698