| 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/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 194 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 213 } | 214 } |
| 214 | 215 |
| 215 | 216 |
| 216 Reduction JSCallReducer::ReduceJSCallFunction(Node* node) { | 217 Reduction JSCallReducer::ReduceJSCallFunction(Node* node) { |
| 217 DCHECK_EQ(IrOpcode::kJSCallFunction, node->opcode()); | 218 DCHECK_EQ(IrOpcode::kJSCallFunction, node->opcode()); |
| 218 CallFunctionParameters const& p = CallFunctionParametersOf(node->op()); | 219 CallFunctionParameters const& p = CallFunctionParametersOf(node->op()); |
| 219 Node* target = NodeProperties::GetValueInput(node, 0); | 220 Node* target = NodeProperties::GetValueInput(node, 0); |
| 220 Node* context = NodeProperties::GetContextInput(node); | 221 Node* context = NodeProperties::GetContextInput(node); |
| 221 Node* control = NodeProperties::GetControlInput(node); | 222 Node* control = NodeProperties::GetControlInput(node); |
| 222 Node* effect = NodeProperties::GetEffectInput(node); | 223 Node* effect = NodeProperties::GetEffectInput(node); |
| 223 Node* frame_state = NodeProperties::FindFrameStateBefore(node); | |
| 224 | 224 |
| 225 // Try to specialize JSCallFunction {node}s with constant {target}s. | 225 // Try to specialize JSCallFunction {node}s with constant {target}s. |
| 226 HeapObjectMatcher m(target); | 226 HeapObjectMatcher m(target); |
| 227 if (m.HasValue()) { | 227 if (m.HasValue()) { |
| 228 if (m.Value()->IsJSFunction()) { | 228 if (m.Value()->IsJSFunction()) { |
| 229 Handle<JSFunction> function = Handle<JSFunction>::cast(m.Value()); | 229 Handle<JSFunction> function = Handle<JSFunction>::cast(m.Value()); |
| 230 Handle<SharedFunctionInfo> shared(function->shared(), isolate()); | 230 Handle<SharedFunctionInfo> shared(function->shared(), isolate()); |
| 231 | 231 |
| 232 // Raise a TypeError if the {target} is a "classConstructor". | 232 // Raise a TypeError if the {target} is a "classConstructor". |
| 233 if (IsClassConstructor(shared->kind())) { | 233 if (IsClassConstructor(shared->kind())) { |
| (...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 316 } else { | 316 } else { |
| 317 Node* native_context = effect = graph()->NewNode( | 317 Node* native_context = effect = graph()->NewNode( |
| 318 javascript()->LoadContext(0, Context::NATIVE_CONTEXT_INDEX, true), | 318 javascript()->LoadContext(0, Context::NATIVE_CONTEXT_INDEX, true), |
| 319 context, context, effect); | 319 context, context, effect); |
| 320 array_function = effect = graph()->NewNode( | 320 array_function = effect = graph()->NewNode( |
| 321 javascript()->LoadContext(0, Context::ARRAY_FUNCTION_INDEX, true), | 321 javascript()->LoadContext(0, Context::ARRAY_FUNCTION_INDEX, true), |
| 322 native_context, native_context, effect); | 322 native_context, native_context, effect); |
| 323 } | 323 } |
| 324 | 324 |
| 325 // Check that the {target} is still the {array_function}. | 325 // Check that the {target} is still the {array_function}. |
| 326 Node* check = graph()->NewNode( | 326 Node* check = graph()->NewNode(simplified()->ReferenceEqual(Type::Any()), |
| 327 javascript()->StrictEqual(CompareOperationHints::Any()), target, | 327 target, array_function); |
| 328 array_function, context); | 328 effect = graph()->NewNode(simplified()->CheckIf(), check, effect, control); |
| 329 control = effect = graph()->NewNode(common()->DeoptimizeUnless(), check, | |
| 330 frame_state, effect, control); | |
| 331 | 329 |
| 332 // Turn the {node} into a {JSCreateArray} call. | 330 // Turn the {node} into a {JSCreateArray} call. |
| 333 NodeProperties::ReplaceValueInput(node, array_function, 0); | 331 NodeProperties::ReplaceValueInput(node, array_function, 0); |
| 334 NodeProperties::ReplaceEffectInput(node, effect); | 332 NodeProperties::ReplaceEffectInput(node, effect); |
| 335 NodeProperties::ReplaceControlInput(node, control); | |
| 336 return ReduceArrayConstructor(node); | 333 return ReduceArrayConstructor(node); |
| 337 } else if (feedback->IsWeakCell()) { | 334 } else if (feedback->IsWeakCell()) { |
| 338 Handle<WeakCell> cell = Handle<WeakCell>::cast(feedback); | 335 Handle<WeakCell> cell = Handle<WeakCell>::cast(feedback); |
| 339 if (cell->value()->IsJSFunction()) { | 336 if (cell->value()->IsJSFunction()) { |
| 340 Node* target_function = | 337 Node* target_function = |
| 341 jsgraph()->Constant(handle(cell->value(), isolate())); | 338 jsgraph()->Constant(handle(cell->value(), isolate())); |
| 342 | 339 |
| 343 // Check that the {target} is still the {target_function}. | 340 // Check that the {target} is still the {target_function}. |
| 344 Node* check = graph()->NewNode( | 341 Node* check = graph()->NewNode(simplified()->ReferenceEqual(Type::Any()), |
| 345 javascript()->StrictEqual(CompareOperationHints::Any()), target, | 342 target, target_function); |
| 346 target_function, context); | 343 effect = |
| 347 control = effect = graph()->NewNode(common()->DeoptimizeUnless(), check, | 344 graph()->NewNode(simplified()->CheckIf(), check, effect, control); |
| 348 frame_state, effect, control); | |
| 349 | 345 |
| 350 // Specialize the JSCallFunction node to the {target_function}. | 346 // Specialize the JSCallFunction node to the {target_function}. |
| 351 NodeProperties::ReplaceValueInput(node, target_function, 0); | 347 NodeProperties::ReplaceValueInput(node, target_function, 0); |
| 352 NodeProperties::ReplaceEffectInput(node, effect); | 348 NodeProperties::ReplaceEffectInput(node, effect); |
| 353 NodeProperties::ReplaceControlInput(node, control); | |
| 354 | 349 |
| 355 // Try to further reduce the JSCallFunction {node}. | 350 // Try to further reduce the JSCallFunction {node}. |
| 356 Reduction const reduction = ReduceJSCallFunction(node); | 351 Reduction const reduction = ReduceJSCallFunction(node); |
| 357 return reduction.Changed() ? reduction : Changed(node); | 352 return reduction.Changed() ? reduction : Changed(node); |
| 358 } | 353 } |
| 359 } | 354 } |
| 360 return NoChange(); | 355 return NoChange(); |
| 361 } | 356 } |
| 362 | 357 |
| 363 | 358 |
| 364 Reduction JSCallReducer::ReduceJSCallConstruct(Node* node) { | 359 Reduction JSCallReducer::ReduceJSCallConstruct(Node* node) { |
| 365 DCHECK_EQ(IrOpcode::kJSCallConstruct, node->opcode()); | 360 DCHECK_EQ(IrOpcode::kJSCallConstruct, node->opcode()); |
| 366 CallConstructParameters const& p = CallConstructParametersOf(node->op()); | 361 CallConstructParameters const& p = CallConstructParametersOf(node->op()); |
| 367 DCHECK_LE(2u, p.arity()); | 362 DCHECK_LE(2u, p.arity()); |
| 368 int const arity = static_cast<int>(p.arity() - 2); | 363 int const arity = static_cast<int>(p.arity() - 2); |
| 369 Node* target = NodeProperties::GetValueInput(node, 0); | 364 Node* target = NodeProperties::GetValueInput(node, 0); |
| 370 Node* new_target = NodeProperties::GetValueInput(node, arity + 1); | 365 Node* new_target = NodeProperties::GetValueInput(node, arity + 1); |
| 371 Node* context = NodeProperties::GetContextInput(node); | 366 Node* context = NodeProperties::GetContextInput(node); |
| 372 Node* effect = NodeProperties::GetEffectInput(node); | 367 Node* effect = NodeProperties::GetEffectInput(node); |
| 373 Node* control = NodeProperties::GetControlInput(node); | 368 Node* control = NodeProperties::GetControlInput(node); |
| 374 Node* frame_state = NodeProperties::FindFrameStateBefore(node); | |
| 375 | 369 |
| 376 // Try to specialize JSCallConstruct {node}s with constant {target}s. | 370 // Try to specialize JSCallConstruct {node}s with constant {target}s. |
| 377 HeapObjectMatcher m(target); | 371 HeapObjectMatcher m(target); |
| 378 if (m.HasValue()) { | 372 if (m.HasValue()) { |
| 379 if (m.Value()->IsJSFunction()) { | 373 if (m.Value()->IsJSFunction()) { |
| 380 Handle<JSFunction> function = Handle<JSFunction>::cast(m.Value()); | 374 Handle<JSFunction> function = Handle<JSFunction>::cast(m.Value()); |
| 381 | 375 |
| 382 // Raise a TypeError if the {target} is not a constructor. | 376 // Raise a TypeError if the {target} is not a constructor. |
| 383 if (!function->IsConstructor()) { | 377 if (!function->IsConstructor()) { |
| 384 NodeProperties::ReplaceValueInputs(node, target); | 378 NodeProperties::ReplaceValueInputs(node, target); |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 438 } else { | 432 } else { |
| 439 Node* native_context = effect = graph()->NewNode( | 433 Node* native_context = effect = graph()->NewNode( |
| 440 javascript()->LoadContext(0, Context::NATIVE_CONTEXT_INDEX, true), | 434 javascript()->LoadContext(0, Context::NATIVE_CONTEXT_INDEX, true), |
| 441 context, context, effect); | 435 context, context, effect); |
| 442 array_function = effect = graph()->NewNode( | 436 array_function = effect = graph()->NewNode( |
| 443 javascript()->LoadContext(0, Context::ARRAY_FUNCTION_INDEX, true), | 437 javascript()->LoadContext(0, Context::ARRAY_FUNCTION_INDEX, true), |
| 444 native_context, native_context, effect); | 438 native_context, native_context, effect); |
| 445 } | 439 } |
| 446 | 440 |
| 447 // Check that the {target} is still the {array_function}. | 441 // Check that the {target} is still the {array_function}. |
| 448 Node* check = graph()->NewNode( | 442 Node* check = graph()->NewNode(simplified()->ReferenceEqual(Type::Any()), |
| 449 javascript()->StrictEqual(CompareOperationHints::Any()), target, | 443 target, array_function); |
| 450 array_function, context); | 444 effect = graph()->NewNode(simplified()->CheckIf(), check, effect, control); |
| 451 control = effect = graph()->NewNode(common()->DeoptimizeUnless(), check, | |
| 452 frame_state, effect, control); | |
| 453 | 445 |
| 454 // Turn the {node} into a {JSCreateArray} call. | 446 // Turn the {node} into a {JSCreateArray} call. |
| 455 NodeProperties::ReplaceEffectInput(node, effect); | 447 NodeProperties::ReplaceEffectInput(node, effect); |
| 456 NodeProperties::ReplaceControlInput(node, control); | |
| 457 for (int i = arity; i > 0; --i) { | 448 for (int i = arity; i > 0; --i) { |
| 458 NodeProperties::ReplaceValueInput( | 449 NodeProperties::ReplaceValueInput( |
| 459 node, NodeProperties::GetValueInput(node, i), i + 1); | 450 node, NodeProperties::GetValueInput(node, i), i + 1); |
| 460 } | 451 } |
| 461 NodeProperties::ReplaceValueInput(node, new_target, 1); | 452 NodeProperties::ReplaceValueInput(node, new_target, 1); |
| 462 NodeProperties::ChangeOp(node, javascript()->CreateArray(arity, site)); | 453 NodeProperties::ChangeOp(node, javascript()->CreateArray(arity, site)); |
| 463 return Changed(node); | 454 return Changed(node); |
| 464 } else if (feedback->IsWeakCell()) { | 455 } else if (feedback->IsWeakCell()) { |
| 465 Handle<WeakCell> cell = Handle<WeakCell>::cast(feedback); | 456 Handle<WeakCell> cell = Handle<WeakCell>::cast(feedback); |
| 466 if (cell->value()->IsJSFunction()) { | 457 if (cell->value()->IsJSFunction()) { |
| 467 Node* target_function = | 458 Node* target_function = |
| 468 jsgraph()->Constant(handle(cell->value(), isolate())); | 459 jsgraph()->Constant(handle(cell->value(), isolate())); |
| 469 | 460 |
| 470 // Check that the {target} is still the {target_function}. | 461 // Check that the {target} is still the {target_function}. |
| 471 Node* check = graph()->NewNode( | 462 Node* check = graph()->NewNode(simplified()->ReferenceEqual(Type::Any()), |
| 472 javascript()->StrictEqual(CompareOperationHints::Any()), target, | 463 target, target_function); |
| 473 target_function, context); | 464 effect = |
| 474 control = effect = graph()->NewNode(common()->DeoptimizeUnless(), check, | 465 graph()->NewNode(simplified()->CheckIf(), check, effect, control); |
| 475 frame_state, effect, control); | |
| 476 | 466 |
| 477 // Specialize the JSCallConstruct node to the {target_function}. | 467 // Specialize the JSCallConstruct node to the {target_function}. |
| 478 NodeProperties::ReplaceValueInput(node, target_function, 0); | 468 NodeProperties::ReplaceValueInput(node, target_function, 0); |
| 479 NodeProperties::ReplaceEffectInput(node, effect); | 469 NodeProperties::ReplaceEffectInput(node, effect); |
| 480 NodeProperties::ReplaceControlInput(node, control); | |
| 481 if (target == new_target) { | 470 if (target == new_target) { |
| 482 NodeProperties::ReplaceValueInput(node, target_function, arity + 1); | 471 NodeProperties::ReplaceValueInput(node, target_function, arity + 1); |
| 483 } | 472 } |
| 484 | 473 |
| 485 // Try to further reduce the JSCallConstruct {node}. | 474 // Try to further reduce the JSCallConstruct {node}. |
| 486 Reduction const reduction = ReduceJSCallConstruct(node); | 475 Reduction const reduction = ReduceJSCallConstruct(node); |
| 487 return reduction.Changed() ? reduction : Changed(node); | 476 return reduction.Changed() ? reduction : Changed(node); |
| 488 } | 477 } |
| 489 } | 478 } |
| 490 | 479 |
| (...skipping 16 matching lines...) Expand all Loading... |
| 507 | 496 |
| 508 CommonOperatorBuilder* JSCallReducer::common() const { | 497 CommonOperatorBuilder* JSCallReducer::common() const { |
| 509 return jsgraph()->common(); | 498 return jsgraph()->common(); |
| 510 } | 499 } |
| 511 | 500 |
| 512 | 501 |
| 513 JSOperatorBuilder* JSCallReducer::javascript() const { | 502 JSOperatorBuilder* JSCallReducer::javascript() const { |
| 514 return jsgraph()->javascript(); | 503 return jsgraph()->javascript(); |
| 515 } | 504 } |
| 516 | 505 |
| 506 SimplifiedOperatorBuilder* JSCallReducer::simplified() const { |
| 507 return jsgraph()->simplified(); |
| 508 } |
| 509 |
| 517 } // namespace compiler | 510 } // namespace compiler |
| 518 } // namespace internal | 511 } // namespace internal |
| 519 } // namespace v8 | 512 } // namespace v8 |
| OLD | NEW |