Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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/code-stubs.h" | 5 #include "src/code-stubs.h" |
| 6 | 6 |
| 7 #include <sstream> | 7 #include <sstream> |
| 8 | 8 |
| 9 #include "src/bootstrapper.h" | 9 #include "src/bootstrapper.h" |
| 10 #include "src/compiler/code-stub-assembler.h" | 10 #include "src/compiler/code-stub-assembler.h" |
| (...skipping 455 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 466 void StringLengthStub::GenerateAssembly( | 466 void StringLengthStub::GenerateAssembly( |
| 467 compiler::CodeStubAssembler* assembler) const { | 467 compiler::CodeStubAssembler* assembler) const { |
| 468 compiler::Node* value = assembler->Parameter(0); | 468 compiler::Node* value = assembler->Parameter(0); |
| 469 compiler::Node* string = | 469 compiler::Node* string = |
| 470 assembler->LoadObjectField(value, JSValue::kValueOffset); | 470 assembler->LoadObjectField(value, JSValue::kValueOffset); |
| 471 compiler::Node* result = | 471 compiler::Node* result = |
| 472 assembler->LoadObjectField(string, String::kLengthOffset); | 472 assembler->LoadObjectField(string, String::kLengthOffset); |
| 473 assembler->Return(result); | 473 assembler->Return(result); |
| 474 } | 474 } |
| 475 | 475 |
| 476 void StrictEqualStub::GenerateAssembly( | |
| 477 compiler::CodeStubAssembler* assembler) const { | |
| 478 typedef compiler::CodeStubAssembler::Label Label; | |
| 479 typedef compiler::Node Node; | |
| 480 | |
| 481 Node* lhs = assembler->Parameter(0); | |
| 482 Node* rhs = assembler->Parameter(1); | |
| 483 Node* context = assembler->Parameter(2); | |
| 484 | |
|
Yang
2016/03/02 10:29:16
This is really hard to read... :P
I'd have preferr
Benedikt Meurer
2016/03/02 11:27:04
Added the pseudo-code thanks. The short-cut unfort
| |
| 485 Label if_true(assembler), if_false(assembler); | |
| 486 | |
| 487 // Check if {lhs} and {rhs} refer to the same object. | |
| 488 Label if_same(assembler), if_notsame(assembler); | |
| 489 assembler->Branch(assembler->WordEqual(lhs, rhs), &if_same, &if_notsame); | |
| 490 | |
| 491 assembler->Bind(&if_same); | |
| 492 { | |
| 493 // The {lhs} and {rhs} reference the exact same value, yet we need special | |
| 494 // treatment for HeapNumber, as NaN is not equal to NaN. | |
| 495 // TODO(bmeurer): This seems to violate the SIMD.js specification, but it | |
| 496 // seems to be what is tested in the current SIMD.js testsuite. | |
| 497 | |
| 498 // Check if {lhs} (and therefore {rhs}) is a Smi or a HeapObject. | |
| 499 Label if_lhsissmi(assembler), if_lhsisnotsmi(assembler); | |
| 500 assembler->Branch(assembler->WordIsSmi(lhs), &if_lhsissmi, &if_lhsisnotsmi); | |
| 501 | |
| 502 assembler->Bind(&if_lhsisnotsmi); | |
| 503 { | |
| 504 // Load the map of {lhs}. | |
| 505 Node* lhs_map = assembler->LoadObjectField(lhs, HeapObject::kMapOffset); | |
| 506 | |
| 507 // Check if {lhs} (and therefore {rhs}) is a HeapNumber. | |
| 508 Node* number_map = assembler->HeapNumberMapConstant(); | |
| 509 Label if_lhsisnumber(assembler), if_lhsisnotnumber(assembler); | |
| 510 assembler->Branch(assembler->WordEqual(lhs_map, number_map), | |
| 511 &if_lhsisnumber, &if_lhsisnotnumber); | |
| 512 | |
| 513 assembler->Bind(&if_lhsisnumber); | |
| 514 { | |
| 515 // Convert {lhs} (and therefore {rhs}) to floating point value. | |
| 516 Node* lhs_value = assembler->LoadHeapNumberValue(lhs); | |
| 517 | |
| 518 // Check if the HeapNumber value is a NaN. | |
| 519 assembler->BranchIfFloat64IsNaN(lhs_value, &if_false, &if_true); | |
| 520 } | |
| 521 | |
| 522 assembler->Bind(&if_lhsisnotnumber); | |
| 523 assembler->Goto(&if_true); | |
| 524 } | |
| 525 | |
| 526 assembler->Bind(&if_lhsissmi); | |
| 527 assembler->Goto(&if_true); | |
| 528 } | |
| 529 | |
| 530 assembler->Bind(&if_notsame); | |
| 531 { | |
| 532 // The {lhs} and {rhs} reference different objects, yet for Smi, HeapNumber, | |
| 533 // String and Simd128Value they can still be considered equal. | |
| 534 Node* number_map = assembler->HeapNumberMapConstant(); | |
| 535 | |
| 536 // Check if {lhs} is a Smi or a HeapObject. | |
| 537 Label if_lhsissmi(assembler), if_lhsisnotsmi(assembler); | |
| 538 assembler->Branch(assembler->WordIsSmi(lhs), &if_lhsissmi, &if_lhsisnotsmi); | |
| 539 | |
| 540 assembler->Bind(&if_lhsisnotsmi); | |
| 541 { | |
| 542 // Load the map of {lhs}. | |
| 543 Node* lhs_map = assembler->LoadObjectField(lhs, HeapObject::kMapOffset); | |
| 544 | |
| 545 // Check if {lhs} is a HeapNumber. | |
| 546 Label if_lhsisnumber(assembler), if_lhsisnotnumber(assembler); | |
| 547 assembler->Branch(assembler->WordEqual(lhs_map, number_map), | |
| 548 &if_lhsisnumber, &if_lhsisnotnumber); | |
| 549 | |
| 550 assembler->Bind(&if_lhsisnumber); | |
| 551 { | |
| 552 // Check if {rhs} is a Smi or a HeapObject. | |
| 553 Label if_rhsissmi(assembler), if_rhsisnotsmi(assembler); | |
| 554 assembler->Branch(assembler->WordIsSmi(rhs), &if_rhsissmi, | |
| 555 &if_rhsisnotsmi); | |
| 556 | |
| 557 assembler->Bind(&if_rhsissmi); | |
| 558 { | |
| 559 // Convert {lhs} and {rhs} to floating point values. | |
| 560 Node* lhs_value = assembler->LoadHeapNumberValue(lhs); | |
| 561 Node* rhs_value = assembler->SmiToFloat64(rhs); | |
| 562 | |
| 563 // Perform a floating point comparison of {lhs} and {rhs}. | |
| 564 assembler->BranchIfFloat64Equal(lhs_value, rhs_value, &if_true, | |
| 565 &if_false); | |
| 566 } | |
| 567 | |
| 568 assembler->Bind(&if_rhsisnotsmi); | |
| 569 { | |
| 570 // Load the map of {rhs}. | |
| 571 Node* rhs_map = | |
| 572 assembler->LoadObjectField(rhs, HeapObject::kMapOffset); | |
| 573 | |
| 574 // Check if {rhs} is also a HeapNumber. | |
| 575 Label if_rhsisnumber(assembler), if_rhsisnotnumber(assembler); | |
| 576 assembler->Branch(assembler->WordEqual(rhs_map, number_map), | |
| 577 &if_rhsisnumber, &if_rhsisnotnumber); | |
| 578 | |
| 579 assembler->Bind(&if_rhsisnumber); | |
| 580 { | |
| 581 // Convert {lhs} and {rhs} to floating point values. | |
| 582 Node* lhs_value = assembler->LoadHeapNumberValue(lhs); | |
| 583 Node* rhs_value = assembler->LoadHeapNumberValue(rhs); | |
| 584 | |
| 585 // Perform a floating point comparison of {lhs} and {rhs}. | |
| 586 assembler->BranchIfFloat64Equal(lhs_value, rhs_value, &if_true, | |
| 587 &if_false); | |
| 588 } | |
| 589 | |
| 590 assembler->Bind(&if_rhsisnotnumber); | |
| 591 assembler->Goto(&if_false); | |
| 592 } | |
| 593 } | |
| 594 | |
| 595 assembler->Bind(&if_lhsisnotnumber); | |
| 596 { | |
| 597 // Check if {rhs} is a Smi or a HeapObject. | |
| 598 Label if_rhsissmi(assembler), if_rhsisnotsmi(assembler); | |
| 599 assembler->Branch(assembler->WordIsSmi(rhs), &if_rhsissmi, | |
| 600 &if_rhsisnotsmi); | |
| 601 | |
| 602 assembler->Bind(&if_rhsissmi); | |
| 603 assembler->Goto(&if_false); | |
| 604 | |
| 605 assembler->Bind(&if_rhsisnotsmi); | |
| 606 { | |
| 607 // Load the instance type of {lhs}. | |
| 608 Node* lhs_instance_type = assembler->LoadMapInstanceType(lhs_map); | |
| 609 | |
| 610 // Check if {lhs} is a String. | |
| 611 Label if_lhsisstring(assembler), if_lhsisnotstring(assembler); | |
| 612 assembler->Branch(assembler->Int32LessThan( | |
| 613 lhs_instance_type, | |
| 614 assembler->Int32Constant(FIRST_NONSTRING_TYPE)), | |
| 615 &if_lhsisstring, &if_lhsisnotstring); | |
| 616 | |
| 617 assembler->Bind(&if_lhsisstring); | |
| 618 { | |
| 619 // Load the instance type of {rhs}. | |
| 620 Node* rhs_instance_type = assembler->LoadInstanceType(rhs); | |
| 621 | |
| 622 // Check if {rhs} is also a String. | |
| 623 Label if_rhsisstring(assembler), if_rhsisnotstring(assembler); | |
| 624 assembler->Branch(assembler->Int32LessThan( | |
| 625 rhs_instance_type, assembler->Int32Constant( | |
| 626 FIRST_NONSTRING_TYPE)), | |
| 627 &if_rhsisstring, &if_rhsisnotstring); | |
| 628 | |
| 629 assembler->Bind(&if_rhsisstring); | |
| 630 { | |
| 631 // TODO(bmeurer): Optimize this further once the StringEqual | |
| 632 // functionality is available in TurboFan land. | |
| 633 assembler->TailCallRuntime(Runtime::kStringEqual, context, lhs, | |
| 634 rhs); | |
| 635 } | |
| 636 | |
| 637 assembler->Bind(&if_rhsisnotstring); | |
| 638 assembler->Goto(&if_false); | |
| 639 } | |
| 640 | |
| 641 assembler->Bind(&if_lhsisnotstring); | |
| 642 { | |
| 643 // Check if {lhs} is a Simd128Value. | |
| 644 Label if_lhsissimd128value(assembler), | |
| 645 if_lhsisnotsimd128value(assembler); | |
| 646 assembler->Branch(assembler->Word32Equal( | |
| 647 lhs_instance_type, | |
| 648 assembler->Int32Constant(SIMD128_VALUE_TYPE)), | |
| 649 &if_lhsissimd128value, &if_lhsisnotsimd128value); | |
| 650 | |
| 651 assembler->Bind(&if_lhsissimd128value); | |
| 652 { | |
| 653 // TODO(bmeurer): Inline the Simd128Value equality check. | |
| 654 assembler->TailCallRuntime(Runtime::kStrictEqual, context, lhs, | |
| 655 rhs); | |
| 656 } | |
| 657 | |
| 658 assembler->Bind(&if_lhsisnotsimd128value); | |
| 659 assembler->Goto(&if_false); | |
| 660 } | |
| 661 } | |
| 662 } | |
| 663 } | |
| 664 | |
| 665 assembler->Bind(&if_lhsissmi); | |
| 666 { | |
| 667 // We already know that {lhs} and {rhs} are not reference equal, and {lhs} | |
| 668 // is a Smi; so {lhs} and {rhs} can only be strictly equal if {rhs} is a | |
| 669 // HeapNumber with an equal floating point value. | |
| 670 | |
| 671 // Check if {rhs} is a Smi or a HeapObject. | |
| 672 Label if_rhsissmi(assembler), if_rhsisnotsmi(assembler); | |
| 673 assembler->Branch(assembler->WordIsSmi(rhs), &if_rhsissmi, | |
| 674 &if_rhsisnotsmi); | |
| 675 | |
| 676 assembler->Bind(&if_rhsissmi); | |
| 677 assembler->Goto(&if_false); | |
| 678 | |
| 679 assembler->Bind(&if_rhsisnotsmi); | |
| 680 { | |
| 681 // Load the map of the {rhs}. | |
| 682 Node* rhs_map = assembler->LoadObjectField(rhs, HeapObject::kMapOffset); | |
| 683 | |
| 684 // The {rhs} could be a HeapNumber with the same value as {lhs}. | |
| 685 Label if_rhsisnumber(assembler), if_rhsisnotnumber(assembler); | |
| 686 assembler->Branch(assembler->WordEqual(rhs_map, number_map), | |
| 687 &if_rhsisnumber, &if_rhsisnotnumber); | |
| 688 | |
| 689 assembler->Bind(&if_rhsisnumber); | |
| 690 { | |
| 691 // Convert {lhs} and {rhs} to floating point values. | |
| 692 Node* lhs_value = assembler->SmiToFloat64(lhs); | |
| 693 Node* rhs_value = assembler->LoadHeapNumberValue(rhs); | |
| 694 | |
| 695 // Perform a floating point comparison of {lhs} and {rhs}. | |
| 696 assembler->BranchIfFloat64Equal(lhs_value, rhs_value, &if_true, | |
| 697 &if_false); | |
| 698 } | |
| 699 | |
| 700 assembler->Bind(&if_rhsisnotnumber); | |
| 701 assembler->Goto(&if_false); | |
| 702 } | |
| 703 } | |
| 704 } | |
| 705 | |
| 706 assembler->Bind(&if_true); | |
| 707 assembler->Return(assembler->BooleanConstant(true)); | |
| 708 | |
| 709 assembler->Bind(&if_false); | |
| 710 assembler->Return(assembler->BooleanConstant(false)); | |
| 711 } | |
| 712 | |
| 476 void ToBooleanStub::GenerateAssembly( | 713 void ToBooleanStub::GenerateAssembly( |
| 477 compiler::CodeStubAssembler* assembler) const { | 714 compiler::CodeStubAssembler* assembler) const { |
| 478 typedef compiler::Node Node; | 715 typedef compiler::Node Node; |
| 479 typedef compiler::CodeStubAssembler::Label Label; | 716 typedef compiler::CodeStubAssembler::Label Label; |
| 480 | 717 |
| 481 Node* value = assembler->Parameter(0); | 718 Node* value = assembler->Parameter(0); |
| 482 Label if_valueissmi(assembler), if_valueisnotsmi(assembler); | 719 Label if_valueissmi(assembler), if_valueisnotsmi(assembler); |
| 483 | 720 |
| 484 // Check if {value} is a Smi or a HeapObject. | 721 // Check if {value} is a Smi or a HeapObject. |
| 485 assembler->Branch(assembler->WordIsSmi(value), &if_valueissmi, | 722 assembler->Branch(assembler->WordIsSmi(value), &if_valueissmi, |
| (...skipping 555 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1041 if (type->Is(Type::UntaggedPointer())) { | 1278 if (type->Is(Type::UntaggedPointer())) { |
| 1042 return Representation::External(); | 1279 return Representation::External(); |
| 1043 } | 1280 } |
| 1044 | 1281 |
| 1045 DCHECK(!type->Is(Type::Untagged())); | 1282 DCHECK(!type->Is(Type::Untagged())); |
| 1046 return Representation::Tagged(); | 1283 return Representation::Tagged(); |
| 1047 } | 1284 } |
| 1048 | 1285 |
| 1049 } // namespace internal | 1286 } // namespace internal |
| 1050 } // namespace v8 | 1287 } // namespace v8 |
| OLD | NEW |