Chromium Code Reviews| 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/access-builder.h" | |
| 10 #include "src/compiler/js-graph.h" | 11 #include "src/compiler/js-graph.h" |
| 11 #include "src/compiler/linkage.h" | 12 #include "src/compiler/linkage.h" |
| 12 #include "src/compiler/node-matchers.h" | 13 #include "src/compiler/node-matchers.h" |
| 13 #include "src/compiler/simplified-operator.h" | 14 #include "src/compiler/simplified-operator.h" |
| 14 #include "src/feedback-vector-inl.h" | 15 #include "src/feedback-vector-inl.h" |
| 15 #include "src/ic/call-optimization.h" | 16 #include "src/ic/call-optimization.h" |
| 16 #include "src/objects-inl.h" | 17 #include "src/objects-inl.h" |
| 17 | 18 |
| 18 namespace v8 { | 19 namespace v8 { |
| 19 namespace internal { | 20 namespace internal { |
| (...skipping 323 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 343 | 344 |
| 344 // ES6 section 26.1.7 Reflect.getPrototypeOf ( target ) | 345 // ES6 section 26.1.7 Reflect.getPrototypeOf ( target ) |
| 345 Reduction JSCallReducer::ReduceReflectGetPrototypeOf(Node* node) { | 346 Reduction JSCallReducer::ReduceReflectGetPrototypeOf(Node* node) { |
| 346 DCHECK_EQ(IrOpcode::kJSCall, node->opcode()); | 347 DCHECK_EQ(IrOpcode::kJSCall, node->opcode()); |
| 347 Node* target = (node->op()->ValueInputCount() >= 3) | 348 Node* target = (node->op()->ValueInputCount() >= 3) |
| 348 ? NodeProperties::GetValueInput(node, 2) | 349 ? NodeProperties::GetValueInput(node, 2) |
| 349 : jsgraph()->UndefinedConstant(); | 350 : jsgraph()->UndefinedConstant(); |
| 350 return ReduceObjectGetPrototype(node, target); | 351 return ReduceObjectGetPrototype(node, target); |
| 351 } | 352 } |
| 352 | 353 |
| 354 Reduction JSCallReducer::ReduceArrayForEach(Handle<SharedFunctionInfo> shared, | |
| 355 Node* node) { | |
| 356 if (!FLAG_inline_array_builtins) return NoChange(); | |
| 357 DCHECK_EQ(IrOpcode::kJSCall, node->opcode()); | |
| 358 Node* outer_frame_state = NodeProperties::GetFrameStateInput(node); | |
| 359 Node* effect = NodeProperties::GetEffectInput(node); | |
| 360 Node* control = NodeProperties::GetControlInput(node); | |
| 361 Node* context = NodeProperties::GetContextInput(node); | |
| 362 CallParameters const& p = CallParametersOf(node->op()); | |
| 363 | |
| 364 // Try to determine the {receiver} map. | |
| 365 Node* receiver = NodeProperties::GetValueInput(node, 1); | |
| 366 Node* fncallback = node->op()->ValueInputCount() > 2 | |
| 367 ? NodeProperties::GetValueInput(node, 2) | |
| 368 : jsgraph()->UndefinedConstant(); | |
| 369 Node* this_arg = node->op()->ValueInputCount() > 3 | |
| 370 ? NodeProperties::GetValueInput(node, 3) | |
| 371 : jsgraph()->UndefinedConstant(); | |
| 372 ZoneHandleSet<Map> receiver_maps; | |
| 373 if (!NodeProperties::InferReceiverMaps(receiver, effect, &receiver_maps)) { | |
|
Benedikt Meurer
2017/05/22 19:29:40
This returns an enum. You only want to deal with r
danno
2017/06/06 12:04:52
Done.
| |
| 374 return NoChange(); | |
| 375 } | |
| 376 if (receiver_maps.size() != 1) return NoChange(); | |
| 377 Handle<Map> receiver_map(receiver_maps[0]); | |
| 378 ElementsKind kind = receiver_map->elements_kind(); | |
| 379 // TODO(danno): Handle holey Smi and Object fast elements kinds and double | |
| 380 // packed. | |
| 381 if (!IsFastPackedElementsKind(kind) || IsFastDoubleElementsKind(kind)) { | |
| 382 return NoChange(); | |
| 383 } | |
| 384 | |
| 385 Node* k = jsgraph()->Constant(0); | |
|
Jarin
2017/05/24 06:41:22
a.k.a. ZeroConstant()
danno
2017/06/06 12:04:52
Done.
| |
| 386 | |
| 387 Node* original_length = graph()->NewNode( | |
| 388 simplified()->LoadField(AccessBuilder::ForJSArrayLength(FAST_ELEMENTS)), | |
| 389 receiver, effect, control); | |
| 390 | |
| 391 Node* loop = control = graph()->NewNode(common()->Loop(2), control, control); | |
| 392 Node* eloop = effect = | |
| 393 graph()->NewNode(common()->EffectPhi(2), effect, effect, loop); | |
| 394 Node* vloop = k = graph()->NewNode( | |
| 395 common()->Phi(MachineRepresentation::kTagged, 2), k, k, loop); | |
| 396 | |
| 397 control = loop; | |
| 398 effect = eloop; | |
| 399 | |
| 400 Node* continue_test = | |
| 401 graph()->NewNode(simplified()->NumberLessThan(), k, original_length); | |
| 402 Node* continue_branch = graph()->NewNode(common()->Branch(BranchHint::kTrue), | |
| 403 continue_test, control); | |
| 404 | |
| 405 Node* if_true = graph()->NewNode(common()->IfTrue(), continue_branch); | |
| 406 Node* if_false = graph()->NewNode(common()->IfFalse(), continue_branch); | |
| 407 control = if_true; | |
| 408 | |
| 409 std::vector<Node*> checkpoint_params( | |
| 410 {receiver, fncallback, this_arg, k, original_length}); | |
| 411 const int stack_parameters = static_cast<int>(checkpoint_params.size()); | |
| 412 | |
| 413 Node* frame_state = CreateJavaScriptBuiltinContinuationFrameState( | |
| 414 jsgraph(), shared, Builtins::kArrayForEachLoopEagerDeoptContinuation, | |
| 415 node->InputAt(0), context, &checkpoint_params[0], stack_parameters, | |
| 416 outer_frame_state, ContinuationFrameStateMode::EAGER); | |
| 417 | |
| 418 effect = | |
| 419 graph()->NewNode(common()->Checkpoint(), frame_state, effect, control); | |
| 420 | |
| 421 // Make sure the map hasn't changed during the iteration | |
| 422 Node* orig_map = jsgraph()->HeapConstant(receiver_map); | |
| 423 Node* array_map = effect = | |
| 424 graph()->NewNode(simplified()->LoadField(AccessBuilder::ForMap()), | |
| 425 receiver, effect, control); | |
| 426 Node* check_map = | |
| 427 graph()->NewNode(simplified()->ReferenceEqual(), array_map, orig_map); | |
| 428 effect = | |
| 429 graph()->NewNode(simplified()->CheckIf(), check_map, effect, control); | |
| 430 | |
| 431 // Make sure that the access is still in bounds, since the callback could have | |
| 432 // changed the array's size. | |
| 433 Node* length = graph()->NewNode( | |
| 434 simplified()->LoadField(AccessBuilder::ForJSArrayLength(FAST_ELEMENTS)), | |
| 435 receiver, effect, control); | |
| 436 k = effect = | |
| 437 graph()->NewNode(simplified()->CheckBounds(), k, length, effect, control); | |
| 438 USE(length); | |
|
Benedikt Meurer
2017/05/22 19:29:40
This is unnecessary.
danno
2017/06/06 12:04:52
Done.
| |
| 439 | |
| 440 // Reload the elements pointer before calling the callback, since the previous | |
| 441 // callback might have resized the array causing the elements buffer to be | |
| 442 // re-allocated. | |
| 443 Node* elements = graph()->NewNode( | |
| 444 simplified()->LoadField(AccessBuilder::ForJSObjectElements()), receiver, | |
| 445 effect, control); | |
| 446 | |
| 447 Node* element = graph()->NewNode( | |
| 448 simplified()->LoadElement(AccessBuilder::ForFixedArrayElement()), | |
| 449 elements, k, effect, control); | |
| 450 | |
| 451 Node* next_k = | |
| 452 graph()->NewNode(simplified()->NumberAdd(), k, jsgraph()->Constant(1)); | |
| 453 checkpoint_params[3] = next_k; | |
| 454 frame_state = CreateJavaScriptBuiltinContinuationFrameState( | |
| 455 jsgraph(), shared, Builtins::kArrayForEachLoopLazyDeoptContinuation, | |
| 456 node->InputAt(0), context, &checkpoint_params[0], stack_parameters, | |
| 457 outer_frame_state, ContinuationFrameStateMode::LAZY); | |
| 458 | |
| 459 Node* call_back = control = effect = graph()->NewNode( | |
| 460 javascript()->Call(5, p.frequency()), fncallback, this_arg, element, k, | |
|
Benedikt Meurer
2017/05/22 19:29:40
This doesn't properly rewire IfException edges. Ca
danno
2017/06/06 12:04:52
Done.
| |
| 461 receiver, context, frame_state, effect, control); | |
| 462 USE(call_back); | |
|
Benedikt Meurer
2017/05/22 19:29:40
You don't seem to need the call_back variable.
danno
2017/06/06 12:04:52
Done.
| |
| 463 USE(this_arg); | |
|
Benedikt Meurer
2017/05/22 19:29:40
This is unnecessary.
danno
2017/06/06 12:04:52
Done.
| |
| 464 | |
| 465 k = next_k; | |
| 466 | |
| 467 loop->ReplaceInput(1, control); | |
| 468 vloop->ReplaceInput(1, k); | |
| 469 eloop->ReplaceInput(1, effect); | |
| 470 | |
| 471 control = if_false; | |
| 472 effect = eloop; | |
| 473 | |
| 474 NodeProperties::ReplaceUses(node, jsgraph()->UndefinedConstant(), effect, | |
|
Benedikt Meurer
2017/05/22 19:29:40
Can you use ReplaceWithValue instead of this magic
Michael Starzinger
2017/05/24 13:54:59
+1, otherwise we might run into similar issues as
danno
2017/06/06 12:04:52
Done.
danno
2017/06/06 12:04:52
Done.
| |
| 475 control); | |
| 476 | |
| 477 node->TrimInputCount(0); | |
| 478 NodeProperties::ChangeOp(node, common()->Dead()); | |
| 479 return Changed(node); | |
| 480 } | |
| 481 | |
| 353 Reduction JSCallReducer::ReduceCallApiFunction( | 482 Reduction JSCallReducer::ReduceCallApiFunction( |
| 354 Node* node, Handle<FunctionTemplateInfo> function_template_info) { | 483 Node* node, Handle<FunctionTemplateInfo> function_template_info) { |
| 355 DCHECK_EQ(IrOpcode::kJSCall, node->opcode()); | 484 DCHECK_EQ(IrOpcode::kJSCall, node->opcode()); |
| 356 CallParameters const& p = CallParametersOf(node->op()); | 485 CallParameters const& p = CallParametersOf(node->op()); |
| 357 int const argc = static_cast<int>(p.arity()) - 2; | 486 int const argc = static_cast<int>(p.arity()) - 2; |
| 358 Node* receiver = (p.convert_mode() == ConvertReceiverMode::kNullOrUndefined) | 487 Node* receiver = (p.convert_mode() == ConvertReceiverMode::kNullOrUndefined) |
| 359 ? jsgraph()->HeapConstant(global_proxy()) | 488 ? jsgraph()->HeapConstant(global_proxy()) |
| 360 : NodeProperties::GetValueInput(node, 1); | 489 : NodeProperties::GetValueInput(node, 1); |
| 361 Node* effect = NodeProperties::GetEffectInput(node); | 490 Node* effect = NodeProperties::GetEffectInput(node); |
| 362 | 491 |
| (...skipping 246 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 609 case Builtins::kFunctionPrototypeHasInstance: | 738 case Builtins::kFunctionPrototypeHasInstance: |
| 610 return ReduceFunctionPrototypeHasInstance(node); | 739 return ReduceFunctionPrototypeHasInstance(node); |
| 611 case Builtins::kNumberConstructor: | 740 case Builtins::kNumberConstructor: |
| 612 return ReduceNumberConstructor(node); | 741 return ReduceNumberConstructor(node); |
| 613 case Builtins::kObjectGetPrototypeOf: | 742 case Builtins::kObjectGetPrototypeOf: |
| 614 return ReduceObjectGetPrototypeOf(node); | 743 return ReduceObjectGetPrototypeOf(node); |
| 615 case Builtins::kObjectPrototypeGetProto: | 744 case Builtins::kObjectPrototypeGetProto: |
| 616 return ReduceObjectPrototypeGetProto(node); | 745 return ReduceObjectPrototypeGetProto(node); |
| 617 case Builtins::kReflectGetPrototypeOf: | 746 case Builtins::kReflectGetPrototypeOf: |
| 618 return ReduceReflectGetPrototypeOf(node); | 747 return ReduceReflectGetPrototypeOf(node); |
| 748 case Builtins::kArrayForEach: | |
| 749 return ReduceArrayForEach(shared, node); | |
| 619 default: | 750 default: |
| 620 break; | 751 break; |
| 621 } | 752 } |
| 622 | 753 |
| 623 // Check for the Array constructor. | 754 // Check for the Array constructor. |
| 624 if (*function == function->native_context()->array_function()) { | 755 if (*function == function->native_context()->array_function()) { |
| 625 return ReduceArrayConstructor(node); | 756 return ReduceArrayConstructor(node); |
| 626 } | 757 } |
| 627 | 758 |
| 628 if (!FLAG_runtime_stats && shared->IsApiFunction()) { | 759 if (!FLAG_runtime_stats && shared->IsApiFunction()) { |
| (...skipping 263 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 892 return jsgraph()->javascript(); | 1023 return jsgraph()->javascript(); |
| 893 } | 1024 } |
| 894 | 1025 |
| 895 SimplifiedOperatorBuilder* JSCallReducer::simplified() const { | 1026 SimplifiedOperatorBuilder* JSCallReducer::simplified() const { |
| 896 return jsgraph()->simplified(); | 1027 return jsgraph()->simplified(); |
| 897 } | 1028 } |
| 898 | 1029 |
| 899 } // namespace compiler | 1030 } // namespace compiler |
| 900 } // namespace internal | 1031 } // namespace internal |
| 901 } // namespace v8 | 1032 } // namespace v8 |
| OLD | NEW |