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/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/objects-inl.h" | 9 #include "src/objects-inl.h" |
10 #include "src/type-feedback-vector-inl.h" | 10 #include "src/type-feedback-vector-inl.h" |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
64 if (feedback->IsAllocationSite()) { | 64 if (feedback->IsAllocationSite()) { |
65 site = Handle<AllocationSite>::cast(feedback); | 65 site = Handle<AllocationSite>::cast(feedback); |
66 } | 66 } |
67 } | 67 } |
68 | 68 |
69 // Turn the {node} into a {JSCreateArray} call. | 69 // Turn the {node} into a {JSCreateArray} call. |
70 DCHECK_LE(2u, p.arity()); | 70 DCHECK_LE(2u, p.arity()); |
71 size_t const arity = p.arity() - 2; | 71 size_t const arity = p.arity() - 2; |
72 NodeProperties::ReplaceValueInput(node, target, 0); | 72 NodeProperties::ReplaceValueInput(node, target, 0); |
73 NodeProperties::ReplaceValueInput(node, target, 1); | 73 NodeProperties::ReplaceValueInput(node, target, 1); |
74 NodeProperties::RemoveFrameStateInput(node, 1); | |
75 // TODO(bmeurer): We might need to propagate the tail call mode to | 74 // TODO(bmeurer): We might need to propagate the tail call mode to |
76 // the JSCreateArray operator, because an Array call in tail call | 75 // the JSCreateArray operator, because an Array call in tail call |
77 // position must always properly consume the parent stack frame. | 76 // position must always properly consume the parent stack frame. |
78 NodeProperties::ChangeOp(node, javascript()->CreateArray(arity, site)); | 77 NodeProperties::ChangeOp(node, javascript()->CreateArray(arity, site)); |
79 return Changed(node); | 78 return Changed(node); |
80 } | 79 } |
81 | 80 |
82 | 81 |
83 // ES6 section 20.1.1 The Number Constructor | 82 // ES6 section 20.1.1 The Number Constructor |
84 Reduction JSCallReducer::ReduceNumberConstructor(Node* node) { | 83 Reduction JSCallReducer::ReduceNumberConstructor(Node* node) { |
85 DCHECK_EQ(IrOpcode::kJSCallFunction, node->opcode()); | 84 DCHECK_EQ(IrOpcode::kJSCallFunction, node->opcode()); |
86 CallFunctionParameters const& p = CallFunctionParametersOf(node->op()); | 85 CallFunctionParameters const& p = CallFunctionParametersOf(node->op()); |
87 | 86 |
88 // Turn the {node} into a {JSToNumber} call. | 87 // Turn the {node} into a {JSToNumber} call. |
89 DCHECK_LE(2u, p.arity()); | 88 DCHECK_LE(2u, p.arity()); |
90 Node* value = (p.arity() == 2) ? jsgraph()->ZeroConstant() | 89 Node* value = (p.arity() == 2) ? jsgraph()->ZeroConstant() |
91 : NodeProperties::GetValueInput(node, 2); | 90 : NodeProperties::GetValueInput(node, 2); |
92 NodeProperties::RemoveFrameStateInput(node, 1); | |
93 NodeProperties::ReplaceValueInputs(node, value); | 91 NodeProperties::ReplaceValueInputs(node, value); |
94 NodeProperties::ChangeOp(node, javascript()->ToNumber()); | 92 NodeProperties::ChangeOp(node, javascript()->ToNumber()); |
95 return Changed(node); | 93 return Changed(node); |
96 } | 94 } |
97 | 95 |
98 | 96 |
99 // ES6 section 19.2.3.1 Function.prototype.apply ( thisArg, argArray ) | 97 // ES6 section 19.2.3.1 Function.prototype.apply ( thisArg, argArray ) |
100 Reduction JSCallReducer::ReduceFunctionPrototypeApply(Node* node) { | 98 Reduction JSCallReducer::ReduceFunctionPrototypeApply(Node* node) { |
101 DCHECK_EQ(IrOpcode::kJSCallFunction, node->opcode()); | 99 DCHECK_EQ(IrOpcode::kJSCallFunction, node->opcode()); |
102 Node* target = NodeProperties::GetValueInput(node, 0); | 100 Node* target = NodeProperties::GetValueInput(node, 0); |
(...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
213 Reduction const reduction = ReduceJSCallFunction(node); | 211 Reduction const reduction = ReduceJSCallFunction(node); |
214 return reduction.Changed() ? reduction : Changed(node); | 212 return reduction.Changed() ? reduction : Changed(node); |
215 } | 213 } |
216 | 214 |
217 | 215 |
218 Reduction JSCallReducer::ReduceJSCallFunction(Node* node) { | 216 Reduction JSCallReducer::ReduceJSCallFunction(Node* node) { |
219 DCHECK_EQ(IrOpcode::kJSCallFunction, node->opcode()); | 217 DCHECK_EQ(IrOpcode::kJSCallFunction, node->opcode()); |
220 CallFunctionParameters const& p = CallFunctionParametersOf(node->op()); | 218 CallFunctionParameters const& p = CallFunctionParametersOf(node->op()); |
221 Node* target = NodeProperties::GetValueInput(node, 0); | 219 Node* target = NodeProperties::GetValueInput(node, 0); |
222 Node* context = NodeProperties::GetContextInput(node); | 220 Node* context = NodeProperties::GetContextInput(node); |
223 Node* frame_state = NodeProperties::GetFrameStateInput(node, 1); | |
224 Node* control = NodeProperties::GetControlInput(node); | 221 Node* control = NodeProperties::GetControlInput(node); |
225 Node* effect = NodeProperties::GetEffectInput(node); | 222 Node* effect = NodeProperties::GetEffectInput(node); |
| 223 Node* frame_state = NodeProperties::FindFrameStateBefore(node); |
226 | 224 |
227 // Try to specialize JSCallFunction {node}s with constant {target}s. | 225 // Try to specialize JSCallFunction {node}s with constant {target}s. |
228 HeapObjectMatcher m(target); | 226 HeapObjectMatcher m(target); |
229 if (m.HasValue()) { | 227 if (m.HasValue()) { |
230 if (m.Value()->IsJSFunction()) { | 228 if (m.Value()->IsJSFunction()) { |
231 Handle<JSFunction> function = Handle<JSFunction>::cast(m.Value()); | 229 Handle<JSFunction> function = Handle<JSFunction>::cast(m.Value()); |
232 Handle<SharedFunctionInfo> shared(function->shared(), isolate()); | 230 Handle<SharedFunctionInfo> shared(function->shared(), isolate()); |
233 | 231 |
234 // Raise a TypeError if the {target} is a "classConstructor". | 232 // Raise a TypeError if the {target} is a "classConstructor". |
235 if (IsClassConstructor(shared->kind())) { | 233 if (IsClassConstructor(shared->kind())) { |
236 NodeProperties::RemoveFrameStateInput(node, 0); | |
237 NodeProperties::ReplaceValueInputs(node, target); | 234 NodeProperties::ReplaceValueInputs(node, target); |
238 NodeProperties::ChangeOp( | 235 NodeProperties::ChangeOp( |
239 node, javascript()->CallRuntime( | 236 node, javascript()->CallRuntime( |
240 Runtime::kThrowConstructorNonCallableError, 1)); | 237 Runtime::kThrowConstructorNonCallableError, 1)); |
241 return Changed(node); | 238 return Changed(node); |
242 } | 239 } |
243 | 240 |
244 // Check for known builtin functions. | 241 // Check for known builtin functions. |
245 if (shared->HasBuiltinFunctionId()) { | 242 if (shared->HasBuiltinFunctionId()) { |
246 switch (shared->builtin_function_id()) { | 243 switch (shared->builtin_function_id()) { |
(...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
363 | 360 |
364 | 361 |
365 Reduction JSCallReducer::ReduceJSCallConstruct(Node* node) { | 362 Reduction JSCallReducer::ReduceJSCallConstruct(Node* node) { |
366 DCHECK_EQ(IrOpcode::kJSCallConstruct, node->opcode()); | 363 DCHECK_EQ(IrOpcode::kJSCallConstruct, node->opcode()); |
367 CallConstructParameters const& p = CallConstructParametersOf(node->op()); | 364 CallConstructParameters const& p = CallConstructParametersOf(node->op()); |
368 DCHECK_LE(2u, p.arity()); | 365 DCHECK_LE(2u, p.arity()); |
369 int const arity = static_cast<int>(p.arity() - 2); | 366 int const arity = static_cast<int>(p.arity() - 2); |
370 Node* target = NodeProperties::GetValueInput(node, 0); | 367 Node* target = NodeProperties::GetValueInput(node, 0); |
371 Node* new_target = NodeProperties::GetValueInput(node, arity + 1); | 368 Node* new_target = NodeProperties::GetValueInput(node, arity + 1); |
372 Node* context = NodeProperties::GetContextInput(node); | 369 Node* context = NodeProperties::GetContextInput(node); |
373 Node* frame_state = NodeProperties::GetFrameStateInput(node, 1); | |
374 Node* effect = NodeProperties::GetEffectInput(node); | 370 Node* effect = NodeProperties::GetEffectInput(node); |
375 Node* control = NodeProperties::GetControlInput(node); | 371 Node* control = NodeProperties::GetControlInput(node); |
| 372 Node* frame_state = NodeProperties::FindFrameStateBefore(node); |
376 | 373 |
377 // Try to specialize JSCallConstruct {node}s with constant {target}s. | 374 // Try to specialize JSCallConstruct {node}s with constant {target}s. |
378 HeapObjectMatcher m(target); | 375 HeapObjectMatcher m(target); |
379 if (m.HasValue()) { | 376 if (m.HasValue()) { |
380 if (m.Value()->IsJSFunction()) { | 377 if (m.Value()->IsJSFunction()) { |
381 Handle<JSFunction> function = Handle<JSFunction>::cast(m.Value()); | 378 Handle<JSFunction> function = Handle<JSFunction>::cast(m.Value()); |
382 | 379 |
383 // Raise a TypeError if the {target} is not a constructor. | 380 // Raise a TypeError if the {target} is not a constructor. |
384 if (!function->IsConstructor()) { | 381 if (!function->IsConstructor()) { |
385 // Drop the lazy bailout location and use the eager bailout point for | |
386 // the runtime function (actually as lazy bailout point). It doesn't | |
387 // really matter which bailout location we use since we never really | |
388 // go back after throwing the exception. | |
389 NodeProperties::RemoveFrameStateInput(node, 0); | |
390 NodeProperties::ReplaceValueInputs(node, target); | 382 NodeProperties::ReplaceValueInputs(node, target); |
391 NodeProperties::ChangeOp( | 383 NodeProperties::ChangeOp( |
392 node, javascript()->CallRuntime(Runtime::kThrowCalledNonCallable)); | 384 node, javascript()->CallRuntime(Runtime::kThrowCalledNonCallable)); |
393 return Changed(node); | 385 return Changed(node); |
394 } | 386 } |
395 | 387 |
396 // Check for the ArrayConstructor. | 388 // Check for the ArrayConstructor. |
397 if (*function == function->native_context()->array_function()) { | 389 if (*function == function->native_context()->array_function()) { |
398 // Check if we have an allocation site. | 390 // Check if we have an allocation site. |
399 Handle<AllocationSite> site; | 391 Handle<AllocationSite> site; |
400 if (p.feedback().IsValid()) { | 392 if (p.feedback().IsValid()) { |
401 Handle<Object> feedback( | 393 Handle<Object> feedback( |
402 p.feedback().vector()->Get(p.feedback().slot()), isolate()); | 394 p.feedback().vector()->Get(p.feedback().slot()), isolate()); |
403 if (feedback->IsAllocationSite()) { | 395 if (feedback->IsAllocationSite()) { |
404 site = Handle<AllocationSite>::cast(feedback); | 396 site = Handle<AllocationSite>::cast(feedback); |
405 } | 397 } |
406 } | 398 } |
407 | 399 |
408 // Turn the {node} into a {JSCreateArray} call. | 400 // Turn the {node} into a {JSCreateArray} call. |
409 NodeProperties::RemoveFrameStateInput(node, 1); | |
410 for (int i = arity; i > 0; --i) { | 401 for (int i = arity; i > 0; --i) { |
411 NodeProperties::ReplaceValueInput( | 402 NodeProperties::ReplaceValueInput( |
412 node, NodeProperties::GetValueInput(node, i), i + 1); | 403 node, NodeProperties::GetValueInput(node, i), i + 1); |
413 } | 404 } |
414 NodeProperties::ReplaceValueInput(node, new_target, 1); | 405 NodeProperties::ReplaceValueInput(node, new_target, 1); |
415 NodeProperties::ChangeOp(node, javascript()->CreateArray(arity, site)); | 406 NodeProperties::ChangeOp(node, javascript()->CreateArray(arity, site)); |
416 return Changed(node); | 407 return Changed(node); |
417 } | 408 } |
418 } | 409 } |
419 | 410 |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
453 | 444 |
454 // Check that the {target} is still the {array_function}. | 445 // Check that the {target} is still the {array_function}. |
455 Node* check = graph()->NewNode(javascript()->StrictEqual(), target, | 446 Node* check = graph()->NewNode(javascript()->StrictEqual(), target, |
456 array_function, context); | 447 array_function, context); |
457 control = effect = graph()->NewNode(common()->DeoptimizeUnless(), check, | 448 control = effect = graph()->NewNode(common()->DeoptimizeUnless(), check, |
458 frame_state, effect, control); | 449 frame_state, effect, control); |
459 | 450 |
460 // Turn the {node} into a {JSCreateArray} call. | 451 // Turn the {node} into a {JSCreateArray} call. |
461 NodeProperties::ReplaceEffectInput(node, effect); | 452 NodeProperties::ReplaceEffectInput(node, effect); |
462 NodeProperties::ReplaceControlInput(node, control); | 453 NodeProperties::ReplaceControlInput(node, control); |
463 NodeProperties::RemoveFrameStateInput(node, 1); | |
464 for (int i = arity; i > 0; --i) { | 454 for (int i = arity; i > 0; --i) { |
465 NodeProperties::ReplaceValueInput( | 455 NodeProperties::ReplaceValueInput( |
466 node, NodeProperties::GetValueInput(node, i), i + 1); | 456 node, NodeProperties::GetValueInput(node, i), i + 1); |
467 } | 457 } |
468 NodeProperties::ReplaceValueInput(node, new_target, 1); | 458 NodeProperties::ReplaceValueInput(node, new_target, 1); |
469 NodeProperties::ChangeOp(node, javascript()->CreateArray(arity, site)); | 459 NodeProperties::ChangeOp(node, javascript()->CreateArray(arity, site)); |
470 return Changed(node); | 460 return Changed(node); |
471 } else if (feedback->IsWeakCell()) { | 461 } else if (feedback->IsWeakCell()) { |
472 Handle<WeakCell> cell = Handle<WeakCell>::cast(feedback); | 462 Handle<WeakCell> cell = Handle<WeakCell>::cast(feedback); |
473 if (cell->value()->IsJSFunction()) { | 463 if (cell->value()->IsJSFunction()) { |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
516 } | 506 } |
517 | 507 |
518 | 508 |
519 JSOperatorBuilder* JSCallReducer::javascript() const { | 509 JSOperatorBuilder* JSCallReducer::javascript() const { |
520 return jsgraph()->javascript(); | 510 return jsgraph()->javascript(); |
521 } | 511 } |
522 | 512 |
523 } // namespace compiler | 513 } // namespace compiler |
524 } // namespace internal | 514 } // namespace internal |
525 } // namespace v8 | 515 } // namespace v8 |
OLD | NEW |