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