| 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 |