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 ToBooleanStub::GenerateAssembly( |
| 477 compiler::CodeStubAssembler* assembler) const { |
| 478 typedef compiler::Node Node; |
| 479 typedef compiler::CodeStubAssembler::Label Label; |
| 480 |
| 481 Node* value = assembler->Parameter(0); |
| 482 Label if_valueissmi(assembler), if_valueisnotsmi(assembler); |
| 483 |
| 484 // Check if {value} is a Smi or a HeapObject. |
| 485 assembler->Branch(assembler->WordIsSmi(value), &if_valueissmi, |
| 486 &if_valueisnotsmi); |
| 487 |
| 488 assembler->Bind(&if_valueissmi); |
| 489 { |
| 490 // The {value} is a Smi, only need to check against zero. |
| 491 Label if_valueiszero(assembler), if_valueisnotzero(assembler); |
| 492 assembler->Branch(assembler->SmiEqual(value, assembler->SmiConstant(0)), |
| 493 &if_valueiszero, &if_valueisnotzero); |
| 494 |
| 495 assembler->Bind(&if_valueiszero); |
| 496 assembler->Return(assembler->BooleanConstant(false)); |
| 497 |
| 498 assembler->Bind(&if_valueisnotzero); |
| 499 assembler->Return(assembler->BooleanConstant(true)); |
| 500 } |
| 501 |
| 502 assembler->Bind(&if_valueisnotsmi); |
| 503 { |
| 504 Label if_valueisstring(assembler), if_valueisheapnumber(assembler), |
| 505 if_valueisoddball(assembler), if_valueisother(assembler); |
| 506 |
| 507 // The {value} is a HeapObject, load its map. |
| 508 Node* value_map = assembler->LoadObjectField(value, HeapObject::kMapOffset); |
| 509 |
| 510 // Load the {value}s instance type. |
| 511 Node* value_instancetype = assembler->Load( |
| 512 MachineType::Uint8(), value_map, |
| 513 assembler->IntPtrConstant(Map::kInstanceTypeOffset - kHeapObjectTag)); |
| 514 |
| 515 // Dispatch based on the instance type; we distinguish all String instance |
| 516 // types, the HeapNumber type and the Oddball type. |
| 517 size_t const kNumCases = FIRST_NONSTRING_TYPE + 2; |
| 518 Label* case_labels[kNumCases]; |
| 519 int32_t case_values[kNumCases]; |
| 520 for (int32_t i = 0; i < FIRST_NONSTRING_TYPE; ++i) { |
| 521 case_labels[i] = new Label(assembler); |
| 522 case_values[i] = i; |
| 523 } |
| 524 case_labels[FIRST_NONSTRING_TYPE + 0] = &if_valueisheapnumber; |
| 525 case_values[FIRST_NONSTRING_TYPE + 0] = HEAP_NUMBER_TYPE; |
| 526 case_labels[FIRST_NONSTRING_TYPE + 1] = &if_valueisoddball; |
| 527 case_values[FIRST_NONSTRING_TYPE + 1] = ODDBALL_TYPE; |
| 528 assembler->Switch(value_instancetype, &if_valueisother, case_values, |
| 529 case_labels, arraysize(case_values)); |
| 530 for (int32_t i = 0; i < FIRST_NONSTRING_TYPE; ++i) { |
| 531 assembler->Bind(case_labels[i]); |
| 532 assembler->Goto(&if_valueisstring); |
| 533 delete case_labels[i]; |
| 534 } |
| 535 |
| 536 assembler->Bind(&if_valueisstring); |
| 537 { |
| 538 // Load the string length field of the {value}. |
| 539 Node* value_length = |
| 540 assembler->LoadObjectField(value, String::kLengthOffset); |
| 541 |
| 542 // Check if the {value} is the empty string. |
| 543 Label if_valueisempty(assembler), if_valueisnotempty(assembler); |
| 544 assembler->Branch( |
| 545 assembler->SmiEqual(value_length, assembler->SmiConstant(0)), |
| 546 &if_valueisempty, &if_valueisnotempty); |
| 547 |
| 548 assembler->Bind(&if_valueisempty); |
| 549 assembler->Return(assembler->BooleanConstant(false)); |
| 550 |
| 551 assembler->Bind(&if_valueisnotempty); |
| 552 assembler->Return(assembler->BooleanConstant(true)); |
| 553 } |
| 554 |
| 555 assembler->Bind(&if_valueisheapnumber); |
| 556 { |
| 557 Node* value_value = assembler->Load( |
| 558 MachineType::Float64(), value, |
| 559 assembler->IntPtrConstant(HeapNumber::kValueOffset - kHeapObjectTag)); |
| 560 |
| 561 Label if_valueispositive(assembler), if_valueisnotpositive(assembler), |
| 562 if_valueisnegative(assembler), if_valueisnanorzero(assembler); |
| 563 assembler->Branch(assembler->Float64LessThan( |
| 564 assembler->Float64Constant(0.0), value_value), |
| 565 &if_valueispositive, &if_valueisnotpositive); |
| 566 |
| 567 assembler->Bind(&if_valueispositive); |
| 568 assembler->Return(assembler->BooleanConstant(true)); |
| 569 |
| 570 assembler->Bind(&if_valueisnotpositive); |
| 571 assembler->Branch(assembler->Float64LessThan( |
| 572 value_value, assembler->Float64Constant(0.0)), |
| 573 &if_valueisnegative, &if_valueisnanorzero); |
| 574 |
| 575 assembler->Bind(&if_valueisnegative); |
| 576 assembler->Return(assembler->BooleanConstant(true)); |
| 577 |
| 578 assembler->Bind(&if_valueisnanorzero); |
| 579 assembler->Return(assembler->BooleanConstant(false)); |
| 580 } |
| 581 |
| 582 assembler->Bind(&if_valueisoddball); |
| 583 { |
| 584 // The {value} is an Oddball, and every Oddball knows its boolean value. |
| 585 Node* value_toboolean = |
| 586 assembler->LoadObjectField(value, Oddball::kToBooleanOffset); |
| 587 assembler->Return(value_toboolean); |
| 588 } |
| 589 |
| 590 assembler->Bind(&if_valueisother); |
| 591 { |
| 592 Node* value_map_bitfield = assembler->Load( |
| 593 MachineType::Uint8(), value_map, |
| 594 assembler->IntPtrConstant(Map::kBitFieldOffset - kHeapObjectTag)); |
| 595 Node* value_map_undetectable = assembler->Word32And( |
| 596 value_map_bitfield, |
| 597 assembler->Int32Constant(1 << Map::kIsUndetectable)); |
| 598 |
| 599 // Check if the {value} is undetectable. |
| 600 Label if_valueisundetectable(assembler), |
| 601 if_valueisnotundetectable(assembler); |
| 602 assembler->Branch(assembler->Word32Equal(value_map_undetectable, |
| 603 assembler->Int32Constant(0)), |
| 604 &if_valueisnotundetectable, &if_valueisundetectable); |
| 605 |
| 606 assembler->Bind(&if_valueisundetectable); |
| 607 assembler->Return(assembler->BooleanConstant(false)); |
| 608 |
| 609 assembler->Bind(&if_valueisnotundetectable); |
| 610 assembler->Return(assembler->BooleanConstant(true)); |
| 611 } |
| 612 } |
| 613 } |
476 | 614 |
477 template<class StateType> | 615 template<class StateType> |
478 void HydrogenCodeStub::TraceTransition(StateType from, StateType to) { | 616 void HydrogenCodeStub::TraceTransition(StateType from, StateType to) { |
479 // Note: Although a no-op transition is semantically OK, it is hinting at a | 617 // Note: Although a no-op transition is semantically OK, it is hinting at a |
480 // bug somewhere in our state transition machinery. | 618 // bug somewhere in our state transition machinery. |
481 DCHECK(from != to); | 619 DCHECK(from != to); |
482 if (!FLAG_trace_ic) return; | 620 if (!FLAG_trace_ic) return; |
483 OFStream os(stdout); | 621 OFStream os(stdout); |
484 os << "["; | 622 os << "["; |
485 PrintBaseName(os); | 623 PrintBaseName(os); |
(...skipping 174 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
660 CodeStubDescriptor* descriptor) { | 798 CodeStubDescriptor* descriptor) { |
661 descriptor->Initialize(); | 799 descriptor->Initialize(); |
662 } | 800 } |
663 | 801 |
664 | 802 |
665 void AllocateInNewSpaceStub::InitializeDescriptor( | 803 void AllocateInNewSpaceStub::InitializeDescriptor( |
666 CodeStubDescriptor* descriptor) { | 804 CodeStubDescriptor* descriptor) { |
667 descriptor->Initialize(); | 805 descriptor->Initialize(); |
668 } | 806 } |
669 | 807 |
670 | 808 void ToBooleanICStub::InitializeDescriptor(CodeStubDescriptor* descriptor) { |
671 void ToBooleanStub::InitializeDescriptor(CodeStubDescriptor* descriptor) { | |
672 descriptor->Initialize(FUNCTION_ADDR(Runtime_ToBooleanIC_Miss)); | 809 descriptor->Initialize(FUNCTION_ADDR(Runtime_ToBooleanIC_Miss)); |
673 descriptor->SetMissHandler(ExternalReference( | 810 descriptor->SetMissHandler(ExternalReference( |
674 Runtime::FunctionForId(Runtime::kToBooleanIC_Miss), isolate())); | 811 Runtime::FunctionForId(Runtime::kToBooleanIC_Miss), isolate())); |
675 } | 812 } |
676 | 813 |
677 | 814 |
678 void BinaryOpICStub::InitializeDescriptor(CodeStubDescriptor* descriptor) { | 815 void BinaryOpICStub::InitializeDescriptor(CodeStubDescriptor* descriptor) { |
679 descriptor->Initialize(FUNCTION_ADDR(Runtime_BinaryOpIC_Miss)); | 816 descriptor->Initialize(FUNCTION_ADDR(Runtime_BinaryOpIC_Miss)); |
680 descriptor->SetMissHandler(ExternalReference( | 817 descriptor->SetMissHandler(ExternalReference( |
681 Runtime::FunctionForId(Runtime::kBinaryOpIC_Miss), isolate())); | 818 Runtime::FunctionForId(Runtime::kBinaryOpIC_Miss), isolate())); |
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
763 std::ostream& ArrayConstructorStubBase::BasePrintName( | 900 std::ostream& ArrayConstructorStubBase::BasePrintName( |
764 std::ostream& os, // NOLINT | 901 std::ostream& os, // NOLINT |
765 const char* name) const { | 902 const char* name) const { |
766 os << name << "_" << ElementsKindToString(elements_kind()); | 903 os << name << "_" << ElementsKindToString(elements_kind()); |
767 if (override_mode() == DISABLE_ALLOCATION_SITES) { | 904 if (override_mode() == DISABLE_ALLOCATION_SITES) { |
768 os << "_DISABLE_ALLOCATION_SITES"; | 905 os << "_DISABLE_ALLOCATION_SITES"; |
769 } | 906 } |
770 return os; | 907 return os; |
771 } | 908 } |
772 | 909 |
773 | 910 bool ToBooleanICStub::UpdateStatus(Handle<Object> object) { |
774 bool ToBooleanStub::UpdateStatus(Handle<Object> object) { | |
775 Types new_types = types(); | 911 Types new_types = types(); |
776 Types old_types = new_types; | 912 Types old_types = new_types; |
777 bool to_boolean_value = new_types.UpdateStatus(object); | 913 bool to_boolean_value = new_types.UpdateStatus(object); |
778 TraceTransition(old_types, new_types); | 914 TraceTransition(old_types, new_types); |
779 set_sub_minor_key(TypesBits::update(sub_minor_key(), new_types.ToIntegral())); | 915 set_sub_minor_key(TypesBits::update(sub_minor_key(), new_types.ToIntegral())); |
780 return to_boolean_value; | 916 return to_boolean_value; |
781 } | 917 } |
782 | 918 |
783 | 919 void ToBooleanICStub::PrintState(std::ostream& os) const { // NOLINT |
784 void ToBooleanStub::PrintState(std::ostream& os) const { // NOLINT | |
785 os << types(); | 920 os << types(); |
786 } | 921 } |
787 | 922 |
788 | 923 std::ostream& operator<<(std::ostream& os, const ToBooleanICStub::Types& s) { |
789 std::ostream& operator<<(std::ostream& os, const ToBooleanStub::Types& s) { | |
790 os << "("; | 924 os << "("; |
791 SimpleListPrinter p(os); | 925 SimpleListPrinter p(os); |
792 if (s.IsEmpty()) p.Add("None"); | 926 if (s.IsEmpty()) p.Add("None"); |
793 if (s.Contains(ToBooleanStub::UNDEFINED)) p.Add("Undefined"); | 927 if (s.Contains(ToBooleanICStub::UNDEFINED)) p.Add("Undefined"); |
794 if (s.Contains(ToBooleanStub::BOOLEAN)) p.Add("Bool"); | 928 if (s.Contains(ToBooleanICStub::BOOLEAN)) p.Add("Bool"); |
795 if (s.Contains(ToBooleanStub::NULL_TYPE)) p.Add("Null"); | 929 if (s.Contains(ToBooleanICStub::NULL_TYPE)) p.Add("Null"); |
796 if (s.Contains(ToBooleanStub::SMI)) p.Add("Smi"); | 930 if (s.Contains(ToBooleanICStub::SMI)) p.Add("Smi"); |
797 if (s.Contains(ToBooleanStub::SPEC_OBJECT)) p.Add("SpecObject"); | 931 if (s.Contains(ToBooleanICStub::SPEC_OBJECT)) p.Add("SpecObject"); |
798 if (s.Contains(ToBooleanStub::STRING)) p.Add("String"); | 932 if (s.Contains(ToBooleanICStub::STRING)) p.Add("String"); |
799 if (s.Contains(ToBooleanStub::SYMBOL)) p.Add("Symbol"); | 933 if (s.Contains(ToBooleanICStub::SYMBOL)) p.Add("Symbol"); |
800 if (s.Contains(ToBooleanStub::HEAP_NUMBER)) p.Add("HeapNumber"); | 934 if (s.Contains(ToBooleanICStub::HEAP_NUMBER)) p.Add("HeapNumber"); |
801 if (s.Contains(ToBooleanStub::SIMD_VALUE)) p.Add("SimdValue"); | 935 if (s.Contains(ToBooleanICStub::SIMD_VALUE)) p.Add("SimdValue"); |
802 return os << ")"; | 936 return os << ")"; |
803 } | 937 } |
804 | 938 |
805 | 939 bool ToBooleanICStub::Types::UpdateStatus(Handle<Object> object) { |
806 bool ToBooleanStub::Types::UpdateStatus(Handle<Object> object) { | |
807 if (object->IsUndefined()) { | 940 if (object->IsUndefined()) { |
808 Add(UNDEFINED); | 941 Add(UNDEFINED); |
809 return false; | 942 return false; |
810 } else if (object->IsBoolean()) { | 943 } else if (object->IsBoolean()) { |
811 Add(BOOLEAN); | 944 Add(BOOLEAN); |
812 return object->IsTrue(); | 945 return object->IsTrue(); |
813 } else if (object->IsNull()) { | 946 } else if (object->IsNull()) { |
814 Add(NULL_TYPE); | 947 Add(NULL_TYPE); |
815 return false; | 948 return false; |
816 } else if (object->IsSmi()) { | 949 } else if (object->IsSmi()) { |
(...skipping 17 matching lines...) Expand all Loading... |
834 } else if (object->IsSimd128Value()) { | 967 } else if (object->IsSimd128Value()) { |
835 Add(SIMD_VALUE); | 968 Add(SIMD_VALUE); |
836 return true; | 969 return true; |
837 } else { | 970 } else { |
838 // We should never see an internal object at runtime here! | 971 // We should never see an internal object at runtime here! |
839 UNREACHABLE(); | 972 UNREACHABLE(); |
840 return true; | 973 return true; |
841 } | 974 } |
842 } | 975 } |
843 | 976 |
844 | 977 bool ToBooleanICStub::Types::NeedsMap() const { |
845 bool ToBooleanStub::Types::NeedsMap() const { | 978 return Contains(ToBooleanICStub::SPEC_OBJECT) || |
846 return Contains(ToBooleanStub::SPEC_OBJECT) || | 979 Contains(ToBooleanICStub::STRING) || |
847 Contains(ToBooleanStub::STRING) || Contains(ToBooleanStub::SYMBOL) || | 980 Contains(ToBooleanICStub::SYMBOL) || |
848 Contains(ToBooleanStub::HEAP_NUMBER) || | 981 Contains(ToBooleanICStub::HEAP_NUMBER) || |
849 Contains(ToBooleanStub::SIMD_VALUE); | 982 Contains(ToBooleanICStub::SIMD_VALUE); |
850 } | 983 } |
851 | 984 |
852 | 985 |
853 void StubFailureTrampolineStub::GenerateAheadOfTime(Isolate* isolate) { | 986 void StubFailureTrampolineStub::GenerateAheadOfTime(Isolate* isolate) { |
854 StubFailureTrampolineStub stub1(isolate, NOT_JS_FUNCTION_STUB_MODE); | 987 StubFailureTrampolineStub stub1(isolate, NOT_JS_FUNCTION_STUB_MODE); |
855 StubFailureTrampolineStub stub2(isolate, JS_FUNCTION_STUB_MODE); | 988 StubFailureTrampolineStub stub2(isolate, JS_FUNCTION_STUB_MODE); |
856 stub1.GetCode(); | 989 stub1.GetCode(); |
857 stub2.GetCode(); | 990 stub2.GetCode(); |
858 } | 991 } |
859 | 992 |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
908 if (type->Is(Type::UntaggedPointer())) { | 1041 if (type->Is(Type::UntaggedPointer())) { |
909 return Representation::External(); | 1042 return Representation::External(); |
910 } | 1043 } |
911 | 1044 |
912 DCHECK(!type->Is(Type::Untagged())); | 1045 DCHECK(!type->Is(Type::Untagged())); |
913 return Representation::Tagged(); | 1046 return Representation::Tagged(); |
914 } | 1047 } |
915 | 1048 |
916 } // namespace internal | 1049 } // namespace internal |
917 } // namespace v8 | 1050 } // namespace v8 |
OLD | NEW |