OLD | NEW |
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/code-factory.h" | 7 #include "src/code-factory.h" |
8 #include "src/code-stubs.h" | 8 #include "src/code-stubs.h" |
9 #include "src/compilation-dependencies.h" | 9 #include "src/compilation-dependencies.h" |
10 #include "src/compiler/js-graph.h" | 10 #include "src/compiler/js-graph.h" |
11 #include "src/compiler/linkage.h" | 11 #include "src/compiler/linkage.h" |
12 #include "src/compiler/node-matchers.h" | 12 #include "src/compiler/node-matchers.h" |
13 #include "src/compiler/simplified-operator.h" | 13 #include "src/compiler/simplified-operator.h" |
14 #include "src/objects-inl.h" | 14 #include "src/objects-inl.h" |
15 #include "src/type-feedback-vector-inl.h" | 15 #include "src/type-feedback-vector-inl.h" |
16 | 16 |
17 namespace v8 { | 17 namespace v8 { |
18 namespace internal { | 18 namespace internal { |
19 namespace compiler { | 19 namespace compiler { |
20 | 20 |
21 Reduction JSCallReducer::Reduce(Node* node) { | 21 Reduction JSCallReducer::Reduce(Node* node) { |
22 switch (node->opcode()) { | 22 switch (node->opcode()) { |
23 case IrOpcode::kJSConstruct: | 23 case IrOpcode::kJSConstruct: |
24 return ReduceJSConstruct(node); | 24 return ReduceJSConstruct(node); |
25 case IrOpcode::kJSConstructWithSpread: | 25 case IrOpcode::kJSConstructWithSpread: |
26 return ReduceJSConstructWithSpread(node); | 26 return ReduceJSConstructWithSpread(node); |
27 case IrOpcode::kJSCallFunction: | 27 case IrOpcode::kJSCall: |
28 return ReduceJSCallFunction(node); | 28 return ReduceJSCall(node); |
29 default: | 29 default: |
30 break; | 30 break; |
31 } | 31 } |
32 return NoChange(); | 32 return NoChange(); |
33 } | 33 } |
34 | 34 |
35 | 35 |
36 // ES6 section 22.1.1 The Array Constructor | 36 // ES6 section 22.1.1 The Array Constructor |
37 Reduction JSCallReducer::ReduceArrayConstructor(Node* node) { | 37 Reduction JSCallReducer::ReduceArrayConstructor(Node* node) { |
38 DCHECK_EQ(IrOpcode::kJSCallFunction, node->opcode()); | 38 DCHECK_EQ(IrOpcode::kJSCall, node->opcode()); |
39 Node* target = NodeProperties::GetValueInput(node, 0); | 39 Node* target = NodeProperties::GetValueInput(node, 0); |
40 CallFunctionParameters const& p = CallFunctionParametersOf(node->op()); | 40 CallParameters const& p = CallParametersOf(node->op()); |
41 | 41 |
42 // Check if we have an allocation site from the CallIC. | 42 // Check if we have an allocation site from the CallIC. |
43 Handle<AllocationSite> site; | 43 Handle<AllocationSite> site; |
44 if (p.feedback().IsValid()) { | 44 if (p.feedback().IsValid()) { |
45 CallICNexus nexus(p.feedback().vector(), p.feedback().slot()); | 45 CallICNexus nexus(p.feedback().vector(), p.feedback().slot()); |
46 Handle<Object> feedback(nexus.GetFeedback(), isolate()); | 46 Handle<Object> feedback(nexus.GetFeedback(), isolate()); |
47 if (feedback->IsAllocationSite()) { | 47 if (feedback->IsAllocationSite()) { |
48 site = Handle<AllocationSite>::cast(feedback); | 48 site = Handle<AllocationSite>::cast(feedback); |
49 } | 49 } |
50 } | 50 } |
51 | 51 |
52 // Turn the {node} into a {JSCreateArray} call. | 52 // Turn the {node} into a {JSCreateArray} call. |
53 DCHECK_LE(2u, p.arity()); | 53 DCHECK_LE(2u, p.arity()); |
54 size_t const arity = p.arity() - 2; | 54 size_t const arity = p.arity() - 2; |
55 NodeProperties::ReplaceValueInput(node, target, 0); | 55 NodeProperties::ReplaceValueInput(node, target, 0); |
56 NodeProperties::ReplaceValueInput(node, target, 1); | 56 NodeProperties::ReplaceValueInput(node, target, 1); |
57 // TODO(bmeurer): We might need to propagate the tail call mode to | 57 // TODO(bmeurer): We might need to propagate the tail call mode to |
58 // the JSCreateArray operator, because an Array call in tail call | 58 // the JSCreateArray operator, because an Array call in tail call |
59 // position must always properly consume the parent stack frame. | 59 // position must always properly consume the parent stack frame. |
60 NodeProperties::ChangeOp(node, javascript()->CreateArray(arity, site)); | 60 NodeProperties::ChangeOp(node, javascript()->CreateArray(arity, site)); |
61 return Changed(node); | 61 return Changed(node); |
62 } | 62 } |
63 | 63 |
64 | 64 |
65 // ES6 section 20.1.1 The Number Constructor | 65 // ES6 section 20.1.1 The Number Constructor |
66 Reduction JSCallReducer::ReduceNumberConstructor(Node* node) { | 66 Reduction JSCallReducer::ReduceNumberConstructor(Node* node) { |
67 DCHECK_EQ(IrOpcode::kJSCallFunction, node->opcode()); | 67 DCHECK_EQ(IrOpcode::kJSCall, node->opcode()); |
68 CallFunctionParameters const& p = CallFunctionParametersOf(node->op()); | 68 CallParameters const& p = CallParametersOf(node->op()); |
69 | 69 |
70 // Turn the {node} into a {JSToNumber} call. | 70 // Turn the {node} into a {JSToNumber} call. |
71 DCHECK_LE(2u, p.arity()); | 71 DCHECK_LE(2u, p.arity()); |
72 Node* value = (p.arity() == 2) ? jsgraph()->ZeroConstant() | 72 Node* value = (p.arity() == 2) ? jsgraph()->ZeroConstant() |
73 : NodeProperties::GetValueInput(node, 2); | 73 : NodeProperties::GetValueInput(node, 2); |
74 NodeProperties::ReplaceValueInputs(node, value); | 74 NodeProperties::ReplaceValueInputs(node, value); |
75 NodeProperties::ChangeOp(node, javascript()->ToNumber()); | 75 NodeProperties::ChangeOp(node, javascript()->ToNumber()); |
76 return Changed(node); | 76 return Changed(node); |
77 } | 77 } |
78 | 78 |
79 | 79 |
80 // ES6 section 19.2.3.1 Function.prototype.apply ( thisArg, argArray ) | 80 // ES6 section 19.2.3.1 Function.prototype.apply ( thisArg, argArray ) |
81 Reduction JSCallReducer::ReduceFunctionPrototypeApply(Node* node) { | 81 Reduction JSCallReducer::ReduceFunctionPrototypeApply(Node* node) { |
82 DCHECK_EQ(IrOpcode::kJSCallFunction, node->opcode()); | 82 DCHECK_EQ(IrOpcode::kJSCall, node->opcode()); |
83 Node* target = NodeProperties::GetValueInput(node, 0); | 83 Node* target = NodeProperties::GetValueInput(node, 0); |
84 CallFunctionParameters const& p = CallFunctionParametersOf(node->op()); | 84 CallParameters const& p = CallParametersOf(node->op()); |
85 // Tail calls to Function.prototype.apply are not properly supported | 85 // Tail calls to Function.prototype.apply are not properly supported |
86 // down the pipeline, so we disable this optimization completely for | 86 // down the pipeline, so we disable this optimization completely for |
87 // tail calls (for now). | 87 // tail calls (for now). |
88 if (p.tail_call_mode() == TailCallMode::kAllow) return NoChange(); | 88 if (p.tail_call_mode() == TailCallMode::kAllow) return NoChange(); |
89 Handle<JSFunction> apply = | 89 Handle<JSFunction> apply = |
90 Handle<JSFunction>::cast(HeapObjectMatcher(target).Value()); | 90 Handle<JSFunction>::cast(HeapObjectMatcher(target).Value()); |
91 size_t arity = p.arity(); | 91 size_t arity = p.arity(); |
92 DCHECK_LE(2u, arity); | 92 DCHECK_LE(2u, arity); |
93 ConvertReceiverMode convert_mode = ConvertReceiverMode::kAny; | 93 ConvertReceiverMode convert_mode = ConvertReceiverMode::kAny; |
94 if (arity == 2) { | 94 if (arity == 2) { |
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
168 node->InsertInput(graph()->zone(), static_cast<int>(arity), | 168 node->InsertInput(graph()->zone(), static_cast<int>(arity), |
169 parameters->InputAt(i)); | 169 parameters->InputAt(i)); |
170 ++arity; | 170 ++arity; |
171 } | 171 } |
172 // Drop the {target} from the {node}. | 172 // Drop the {target} from the {node}. |
173 node->RemoveInput(0); | 173 node->RemoveInput(0); |
174 --arity; | 174 --arity; |
175 } else { | 175 } else { |
176 return NoChange(); | 176 return NoChange(); |
177 } | 177 } |
178 // Change {node} to the new {JSCallFunction} operator. | 178 // Change {node} to the new {JSCall} operator. |
179 NodeProperties::ChangeOp( | 179 NodeProperties::ChangeOp( |
180 node, javascript()->CallFunction(arity, p.frequency(), VectorSlotPair(), | 180 node, |
181 convert_mode, p.tail_call_mode())); | 181 javascript()->Call(arity, p.frequency(), VectorSlotPair(), convert_mode, |
| 182 p.tail_call_mode())); |
182 // Change context of {node} to the Function.prototype.apply context, | 183 // Change context of {node} to the Function.prototype.apply context, |
183 // to ensure any exception is thrown in the correct context. | 184 // to ensure any exception is thrown in the correct context. |
184 NodeProperties::ReplaceContextInput( | 185 NodeProperties::ReplaceContextInput( |
185 node, jsgraph()->HeapConstant(handle(apply->context(), isolate()))); | 186 node, jsgraph()->HeapConstant(handle(apply->context(), isolate()))); |
186 // Try to further reduce the JSCallFunction {node}. | 187 // Try to further reduce the JSCall {node}. |
187 Reduction const reduction = ReduceJSCallFunction(node); | 188 Reduction const reduction = ReduceJSCall(node); |
188 return reduction.Changed() ? reduction : Changed(node); | 189 return reduction.Changed() ? reduction : Changed(node); |
189 } | 190 } |
190 | 191 |
191 | 192 |
192 // ES6 section 19.2.3.3 Function.prototype.call (thisArg, ...args) | 193 // ES6 section 19.2.3.3 Function.prototype.call (thisArg, ...args) |
193 Reduction JSCallReducer::ReduceFunctionPrototypeCall(Node* node) { | 194 Reduction JSCallReducer::ReduceFunctionPrototypeCall(Node* node) { |
194 DCHECK_EQ(IrOpcode::kJSCallFunction, node->opcode()); | 195 DCHECK_EQ(IrOpcode::kJSCall, node->opcode()); |
195 CallFunctionParameters const& p = CallFunctionParametersOf(node->op()); | 196 CallParameters const& p = CallParametersOf(node->op()); |
196 Handle<JSFunction> call = Handle<JSFunction>::cast( | 197 Handle<JSFunction> call = Handle<JSFunction>::cast( |
197 HeapObjectMatcher(NodeProperties::GetValueInput(node, 0)).Value()); | 198 HeapObjectMatcher(NodeProperties::GetValueInput(node, 0)).Value()); |
198 // Change context of {node} to the Function.prototype.call context, | 199 // Change context of {node} to the Function.prototype.call context, |
199 // to ensure any exception is thrown in the correct context. | 200 // to ensure any exception is thrown in the correct context. |
200 NodeProperties::ReplaceContextInput( | 201 NodeProperties::ReplaceContextInput( |
201 node, jsgraph()->HeapConstant(handle(call->context(), isolate()))); | 202 node, jsgraph()->HeapConstant(handle(call->context(), isolate()))); |
202 // Remove the target from {node} and use the receiver as target instead, and | 203 // Remove the target from {node} and use the receiver as target instead, and |
203 // the thisArg becomes the new target. If thisArg was not provided, insert | 204 // the thisArg becomes the new target. If thisArg was not provided, insert |
204 // undefined instead. | 205 // undefined instead. |
205 size_t arity = p.arity(); | 206 size_t arity = p.arity(); |
206 DCHECK_LE(2u, arity); | 207 DCHECK_LE(2u, arity); |
207 ConvertReceiverMode convert_mode; | 208 ConvertReceiverMode convert_mode; |
208 if (arity == 2) { | 209 if (arity == 2) { |
209 // The thisArg was not provided, use undefined as receiver. | 210 // The thisArg was not provided, use undefined as receiver. |
210 convert_mode = ConvertReceiverMode::kNullOrUndefined; | 211 convert_mode = ConvertReceiverMode::kNullOrUndefined; |
211 node->ReplaceInput(0, node->InputAt(1)); | 212 node->ReplaceInput(0, node->InputAt(1)); |
212 node->ReplaceInput(1, jsgraph()->UndefinedConstant()); | 213 node->ReplaceInput(1, jsgraph()->UndefinedConstant()); |
213 } else { | 214 } else { |
214 // Just remove the target, which is the first value input. | 215 // Just remove the target, which is the first value input. |
215 convert_mode = ConvertReceiverMode::kAny; | 216 convert_mode = ConvertReceiverMode::kAny; |
216 node->RemoveInput(0); | 217 node->RemoveInput(0); |
217 --arity; | 218 --arity; |
218 } | 219 } |
219 NodeProperties::ChangeOp( | 220 NodeProperties::ChangeOp( |
220 node, javascript()->CallFunction(arity, p.frequency(), VectorSlotPair(), | 221 node, |
221 convert_mode, p.tail_call_mode())); | 222 javascript()->Call(arity, p.frequency(), VectorSlotPair(), convert_mode, |
222 // Try to further reduce the JSCallFunction {node}. | 223 p.tail_call_mode())); |
223 Reduction const reduction = ReduceJSCallFunction(node); | 224 // Try to further reduce the JSCall {node}. |
| 225 Reduction const reduction = ReduceJSCall(node); |
224 return reduction.Changed() ? reduction : Changed(node); | 226 return reduction.Changed() ? reduction : Changed(node); |
225 } | 227 } |
226 | 228 |
227 // ES6 section 19.2.3.6 Function.prototype [ @@hasInstance ] (V) | 229 // ES6 section 19.2.3.6 Function.prototype [ @@hasInstance ] (V) |
228 Reduction JSCallReducer::ReduceFunctionPrototypeHasInstance(Node* node) { | 230 Reduction JSCallReducer::ReduceFunctionPrototypeHasInstance(Node* node) { |
229 DCHECK_EQ(IrOpcode::kJSCallFunction, node->opcode()); | 231 DCHECK_EQ(IrOpcode::kJSCall, node->opcode()); |
230 Node* receiver = NodeProperties::GetValueInput(node, 1); | 232 Node* receiver = NodeProperties::GetValueInput(node, 1); |
231 Node* object = (node->op()->ValueInputCount() >= 3) | 233 Node* object = (node->op()->ValueInputCount() >= 3) |
232 ? NodeProperties::GetValueInput(node, 2) | 234 ? NodeProperties::GetValueInput(node, 2) |
233 : jsgraph()->UndefinedConstant(); | 235 : jsgraph()->UndefinedConstant(); |
234 Node* context = NodeProperties::GetContextInput(node); | 236 Node* context = NodeProperties::GetContextInput(node); |
235 Node* frame_state = NodeProperties::GetFrameStateInput(node); | 237 Node* frame_state = NodeProperties::GetFrameStateInput(node); |
236 Node* effect = NodeProperties::GetEffectInput(node); | 238 Node* effect = NodeProperties::GetEffectInput(node); |
237 Node* control = NodeProperties::GetControlInput(node); | 239 Node* control = NodeProperties::GetControlInput(node); |
238 | 240 |
239 // TODO(turbofan): If JSOrdinaryToInstance raises an exception, the | 241 // TODO(turbofan): If JSOrdinaryToInstance raises an exception, the |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
274 if (dominator->op()->EffectInputCount() != 1) { | 276 if (dominator->op()->EffectInputCount() != 1) { |
275 // Didn't find any appropriate CheckMaps node. | 277 // Didn't find any appropriate CheckMaps node. |
276 return MaybeHandle<Map>(); | 278 return MaybeHandle<Map>(); |
277 } | 279 } |
278 dominator = NodeProperties::GetEffectInput(dominator); | 280 dominator = NodeProperties::GetEffectInput(dominator); |
279 } | 281 } |
280 } | 282 } |
281 | 283 |
282 bool CanInlineApiCall(Isolate* isolate, Node* node, | 284 bool CanInlineApiCall(Isolate* isolate, Node* node, |
283 Handle<FunctionTemplateInfo> function_template_info) { | 285 Handle<FunctionTemplateInfo> function_template_info) { |
284 DCHECK(node->opcode() == IrOpcode::kJSCallFunction); | 286 DCHECK(node->opcode() == IrOpcode::kJSCall); |
285 if (V8_UNLIKELY(FLAG_runtime_stats)) return false; | 287 if (V8_UNLIKELY(FLAG_runtime_stats)) return false; |
286 if (function_template_info->call_code()->IsUndefined(isolate)) { | 288 if (function_template_info->call_code()->IsUndefined(isolate)) { |
287 return false; | 289 return false; |
288 } | 290 } |
289 CallFunctionParameters const& params = CallFunctionParametersOf(node->op()); | 291 CallParameters const& params = CallParametersOf(node->op()); |
290 // CallApiCallbackStub expects the target in a register, so we count it out, | 292 // CallApiCallbackStub expects the target in a register, so we count it out, |
291 // and counts the receiver as an implicit argument, so we count the receiver | 293 // and counts the receiver as an implicit argument, so we count the receiver |
292 // out too. | 294 // out too. |
293 int const argc = static_cast<int>(params.arity()) - 2; | 295 int const argc = static_cast<int>(params.arity()) - 2; |
294 if (argc > CallApiCallbackStub::kArgMax || !params.feedback().IsValid()) { | 296 if (argc > CallApiCallbackStub::kArgMax || !params.feedback().IsValid()) { |
295 return false; | 297 return false; |
296 } | 298 } |
297 HeapObjectMatcher receiver(NodeProperties::GetValueInput(node, 1)); | 299 HeapObjectMatcher receiver(NodeProperties::GetValueInput(node, 1)); |
298 if (!receiver.HasValue()) { | 300 if (!receiver.HasValue()) { |
299 return false; | 301 return false; |
(...skipping 27 matching lines...) Expand all Loading... |
327 if (expected_receiver_type->IsTemplateFor(*object_map)) { | 329 if (expected_receiver_type->IsTemplateFor(*object_map)) { |
328 *holder = prototype; | 330 *holder = prototype; |
329 return kHolderFound; | 331 return kHolderFound; |
330 } | 332 } |
331 } | 333 } |
332 return kHolderNotFound; | 334 return kHolderNotFound; |
333 } | 335 } |
334 | 336 |
335 // ES6 section B.2.2.1.1 get Object.prototype.__proto__ | 337 // ES6 section B.2.2.1.1 get Object.prototype.__proto__ |
336 Reduction JSCallReducer::ReduceObjectPrototypeGetProto(Node* node) { | 338 Reduction JSCallReducer::ReduceObjectPrototypeGetProto(Node* node) { |
337 DCHECK_EQ(IrOpcode::kJSCallFunction, node->opcode()); | 339 DCHECK_EQ(IrOpcode::kJSCall, node->opcode()); |
338 | 340 |
339 // Try to determine the {receiver} map. | 341 // Try to determine the {receiver} map. |
340 Handle<Map> receiver_map; | 342 Handle<Map> receiver_map; |
341 if (InferReceiverMap(node).ToHandle(&receiver_map)) { | 343 if (InferReceiverMap(node).ToHandle(&receiver_map)) { |
342 // Check if we can constant-fold the {receiver} map. | 344 // Check if we can constant-fold the {receiver} map. |
343 if (!receiver_map->IsJSProxyMap() && | 345 if (!receiver_map->IsJSProxyMap() && |
344 !receiver_map->has_hidden_prototype() && | 346 !receiver_map->has_hidden_prototype() && |
345 !receiver_map->is_access_check_needed()) { | 347 !receiver_map->is_access_check_needed()) { |
346 Handle<Object> receiver_prototype(receiver_map->prototype(), isolate()); | 348 Handle<Object> receiver_prototype(receiver_map->prototype(), isolate()); |
347 Node* value = jsgraph()->Constant(receiver_prototype); | 349 Node* value = jsgraph()->Constant(receiver_prototype); |
(...skipping 13 matching lines...) Expand all Loading... |
361 HeapObjectMatcher m(target); | 363 HeapObjectMatcher m(target); |
362 DCHECK(m.HasValue() && m.Value()->IsJSFunction()); | 364 DCHECK(m.HasValue() && m.Value()->IsJSFunction()); |
363 if (!CanInlineApiCall(isolate, node, function_template_info)) { | 365 if (!CanInlineApiCall(isolate, node, function_template_info)) { |
364 return NoChange(); | 366 return NoChange(); |
365 } | 367 } |
366 Handle<CallHandlerInfo> call_handler_info( | 368 Handle<CallHandlerInfo> call_handler_info( |
367 handle(CallHandlerInfo::cast(function_template_info->call_code()))); | 369 handle(CallHandlerInfo::cast(function_template_info->call_code()))); |
368 Handle<Object> data(call_handler_info->data(), isolate); | 370 Handle<Object> data(call_handler_info->data(), isolate); |
369 | 371 |
370 Node* receiver_node = NodeProperties::GetValueInput(node, 1); | 372 Node* receiver_node = NodeProperties::GetValueInput(node, 1); |
371 CallFunctionParameters const& params = CallFunctionParametersOf(node->op()); | 373 CallParameters const& params = CallParametersOf(node->op()); |
372 | 374 |
373 Handle<HeapObject> receiver = HeapObjectMatcher(receiver_node).Value(); | 375 Handle<HeapObject> receiver = HeapObjectMatcher(receiver_node).Value(); |
374 bool const receiver_is_undefined = receiver->IsUndefined(isolate); | 376 bool const receiver_is_undefined = receiver->IsUndefined(isolate); |
375 if (receiver_is_undefined) { | 377 if (receiver_is_undefined) { |
376 receiver = handle(Handle<JSFunction>::cast(m.Value())->global_proxy()); | 378 receiver = handle(Handle<JSFunction>::cast(m.Value())->global_proxy()); |
377 } else { | 379 } else { |
378 DCHECK(receiver->map()->IsJSObjectMap() && | 380 DCHECK(receiver->map()->IsJSObjectMap() && |
379 !receiver->map()->is_access_check_needed()); | 381 !receiver->map()->is_access_check_needed()); |
380 } | 382 } |
381 | 383 |
(...skipping 27 matching lines...) Expand all Loading... |
409 // CallApiCallbackStub's register arguments: code, target, call data, holder, | 411 // CallApiCallbackStub's register arguments: code, target, call data, holder, |
410 // function address. | 412 // function address. |
411 node->InsertInput(zone, 0, jsgraph()->HeapConstant(stub.GetCode())); | 413 node->InsertInput(zone, 0, jsgraph()->HeapConstant(stub.GetCode())); |
412 node->InsertInput(zone, 2, jsgraph()->Constant(data)); | 414 node->InsertInput(zone, 2, jsgraph()->Constant(data)); |
413 node->InsertInput(zone, 3, holder_node); | 415 node->InsertInput(zone, 3, holder_node); |
414 node->InsertInput(zone, 4, jsgraph()->ExternalConstant(function_reference)); | 416 node->InsertInput(zone, 4, jsgraph()->ExternalConstant(function_reference)); |
415 NodeProperties::ChangeOp(node, common()->Call(call_descriptor)); | 417 NodeProperties::ChangeOp(node, common()->Call(call_descriptor)); |
416 return Changed(node); | 418 return Changed(node); |
417 } | 419 } |
418 | 420 |
419 Reduction JSCallReducer::ReduceJSCallFunction(Node* node) { | 421 Reduction JSCallReducer::ReduceJSCall(Node* node) { |
420 DCHECK_EQ(IrOpcode::kJSCallFunction, node->opcode()); | 422 DCHECK_EQ(IrOpcode::kJSCall, node->opcode()); |
421 CallFunctionParameters const& p = CallFunctionParametersOf(node->op()); | 423 CallParameters const& p = CallParametersOf(node->op()); |
422 Node* target = NodeProperties::GetValueInput(node, 0); | 424 Node* target = NodeProperties::GetValueInput(node, 0); |
423 Node* control = NodeProperties::GetControlInput(node); | 425 Node* control = NodeProperties::GetControlInput(node); |
424 Node* effect = NodeProperties::GetEffectInput(node); | 426 Node* effect = NodeProperties::GetEffectInput(node); |
425 | 427 |
426 // Try to specialize JSCallFunction {node}s with constant {target}s. | 428 // Try to specialize JSCall {node}s with constant {target}s. |
427 HeapObjectMatcher m(target); | 429 HeapObjectMatcher m(target); |
428 if (m.HasValue()) { | 430 if (m.HasValue()) { |
429 if (m.Value()->IsJSFunction()) { | 431 if (m.Value()->IsJSFunction()) { |
430 Handle<JSFunction> function = Handle<JSFunction>::cast(m.Value()); | 432 Handle<JSFunction> function = Handle<JSFunction>::cast(m.Value()); |
431 Handle<SharedFunctionInfo> shared(function->shared(), isolate()); | 433 Handle<SharedFunctionInfo> shared(function->shared(), isolate()); |
432 | 434 |
433 // Raise a TypeError if the {target} is a "classConstructor". | 435 // Raise a TypeError if the {target} is a "classConstructor". |
434 if (IsClassConstructor(shared->kind())) { | 436 if (IsClassConstructor(shared->kind())) { |
435 NodeProperties::ReplaceValueInputs(node, target); | 437 NodeProperties::ReplaceValueInputs(node, target); |
436 NodeProperties::ChangeOp( | 438 NodeProperties::ChangeOp( |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
469 handle(FunctionTemplateInfo::cast(shared->function_data()))); | 471 handle(FunctionTemplateInfo::cast(shared->function_data()))); |
470 } | 472 } |
471 } else if (m.Value()->IsJSBoundFunction()) { | 473 } else if (m.Value()->IsJSBoundFunction()) { |
472 Handle<JSBoundFunction> function = | 474 Handle<JSBoundFunction> function = |
473 Handle<JSBoundFunction>::cast(m.Value()); | 475 Handle<JSBoundFunction>::cast(m.Value()); |
474 Handle<JSReceiver> bound_target_function( | 476 Handle<JSReceiver> bound_target_function( |
475 function->bound_target_function(), isolate()); | 477 function->bound_target_function(), isolate()); |
476 Handle<Object> bound_this(function->bound_this(), isolate()); | 478 Handle<Object> bound_this(function->bound_this(), isolate()); |
477 Handle<FixedArray> bound_arguments(function->bound_arguments(), | 479 Handle<FixedArray> bound_arguments(function->bound_arguments(), |
478 isolate()); | 480 isolate()); |
479 CallFunctionParameters const& p = CallFunctionParametersOf(node->op()); | 481 CallParameters const& p = CallParametersOf(node->op()); |
480 ConvertReceiverMode const convert_mode = | 482 ConvertReceiverMode const convert_mode = |
481 (bound_this->IsNullOrUndefined(isolate())) | 483 (bound_this->IsNullOrUndefined(isolate())) |
482 ? ConvertReceiverMode::kNullOrUndefined | 484 ? ConvertReceiverMode::kNullOrUndefined |
483 : ConvertReceiverMode::kNotNullOrUndefined; | 485 : ConvertReceiverMode::kNotNullOrUndefined; |
484 size_t arity = p.arity(); | 486 size_t arity = p.arity(); |
485 DCHECK_LE(2u, arity); | 487 DCHECK_LE(2u, arity); |
486 // Patch {node} to use [[BoundTargetFunction]] and [[BoundThis]]. | 488 // Patch {node} to use [[BoundTargetFunction]] and [[BoundThis]]. |
487 NodeProperties::ReplaceValueInput( | 489 NodeProperties::ReplaceValueInput( |
488 node, jsgraph()->Constant(bound_target_function), 0); | 490 node, jsgraph()->Constant(bound_target_function), 0); |
489 NodeProperties::ReplaceValueInput(node, jsgraph()->Constant(bound_this), | 491 NodeProperties::ReplaceValueInput(node, jsgraph()->Constant(bound_this), |
490 1); | 492 1); |
491 // Insert the [[BoundArguments]] for {node}. | 493 // Insert the [[BoundArguments]] for {node}. |
492 for (int i = 0; i < bound_arguments->length(); ++i) { | 494 for (int i = 0; i < bound_arguments->length(); ++i) { |
493 node->InsertInput( | 495 node->InsertInput( |
494 graph()->zone(), i + 2, | 496 graph()->zone(), i + 2, |
495 jsgraph()->Constant(handle(bound_arguments->get(i), isolate()))); | 497 jsgraph()->Constant(handle(bound_arguments->get(i), isolate()))); |
496 arity++; | 498 arity++; |
497 } | 499 } |
498 NodeProperties::ChangeOp(node, javascript()->CallFunction( | 500 NodeProperties::ChangeOp( |
499 arity, p.frequency(), VectorSlotPair(), | 501 node, |
500 convert_mode, p.tail_call_mode())); | 502 javascript()->Call(arity, p.frequency(), VectorSlotPair(), |
501 // Try to further reduce the JSCallFunction {node}. | 503 convert_mode, p.tail_call_mode())); |
502 Reduction const reduction = ReduceJSCallFunction(node); | 504 // Try to further reduce the JSCall {node}. |
| 505 Reduction const reduction = ReduceJSCall(node); |
503 return reduction.Changed() ? reduction : Changed(node); | 506 return reduction.Changed() ? reduction : Changed(node); |
504 } | 507 } |
505 | 508 |
506 // Don't mess with other {node}s that have a constant {target}. | 509 // Don't mess with other {node}s that have a constant {target}. |
507 // TODO(bmeurer): Also support proxies here. | 510 // TODO(bmeurer): Also support proxies here. |
508 return NoChange(); | 511 return NoChange(); |
509 } | 512 } |
510 | 513 |
511 // Extract feedback from the {node} using the CallICNexus. | 514 // Extract feedback from the {node} using the CallICNexus. |
512 if (!p.feedback().IsValid()) return NoChange(); | 515 if (!p.feedback().IsValid()) return NoChange(); |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
559 if (cell->value()->IsJSFunction()) { | 562 if (cell->value()->IsJSFunction()) { |
560 Node* target_function = | 563 Node* target_function = |
561 jsgraph()->Constant(handle(cell->value(), isolate())); | 564 jsgraph()->Constant(handle(cell->value(), isolate())); |
562 | 565 |
563 // Check that the {target} is still the {target_function}. | 566 // Check that the {target} is still the {target_function}. |
564 Node* check = graph()->NewNode(simplified()->ReferenceEqual(), target, | 567 Node* check = graph()->NewNode(simplified()->ReferenceEqual(), target, |
565 target_function); | 568 target_function); |
566 effect = | 569 effect = |
567 graph()->NewNode(simplified()->CheckIf(), check, effect, control); | 570 graph()->NewNode(simplified()->CheckIf(), check, effect, control); |
568 | 571 |
569 // Specialize the JSCallFunction node to the {target_function}. | 572 // Specialize the JSCall node to the {target_function}. |
570 NodeProperties::ReplaceValueInput(node, target_function, 0); | 573 NodeProperties::ReplaceValueInput(node, target_function, 0); |
571 NodeProperties::ReplaceEffectInput(node, effect); | 574 NodeProperties::ReplaceEffectInput(node, effect); |
572 | 575 |
573 // Try to further reduce the JSCallFunction {node}. | 576 // Try to further reduce the JSCall {node}. |
574 Reduction const reduction = ReduceJSCallFunction(node); | 577 Reduction const reduction = ReduceJSCall(node); |
575 return reduction.Changed() ? reduction : Changed(node); | 578 return reduction.Changed() ? reduction : Changed(node); |
576 } | 579 } |
577 } | 580 } |
578 return NoChange(); | 581 return NoChange(); |
579 } | 582 } |
580 | 583 |
581 Reduction JSCallReducer::ReduceJSConstruct(Node* node) { | 584 Reduction JSCallReducer::ReduceJSConstruct(Node* node) { |
582 DCHECK_EQ(IrOpcode::kJSConstruct, node->opcode()); | 585 DCHECK_EQ(IrOpcode::kJSConstruct, node->opcode()); |
583 ConstructParameters const& p = ConstructParametersOf(node->op()); | 586 ConstructParameters const& p = ConstructParametersOf(node->op()); |
584 DCHECK_LE(2u, p.arity()); | 587 DCHECK_LE(2u, p.arity()); |
(...skipping 195 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
780 return jsgraph()->javascript(); | 783 return jsgraph()->javascript(); |
781 } | 784 } |
782 | 785 |
783 SimplifiedOperatorBuilder* JSCallReducer::simplified() const { | 786 SimplifiedOperatorBuilder* JSCallReducer::simplified() const { |
784 return jsgraph()->simplified(); | 787 return jsgraph()->simplified(); |
785 } | 788 } |
786 | 789 |
787 } // namespace compiler | 790 } // namespace compiler |
788 } // namespace internal | 791 } // namespace internal |
789 } // namespace v8 | 792 } // namespace v8 |
OLD | NEW |