OLD | NEW |
1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 694 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
705 __ JumpIfNotSmi(rax, &non_smi_value); | 705 __ JumpIfNotSmi(rax, &non_smi_value); |
706 // It's irrelevant whether array is smi-only or not when writing a smi. | 706 // It's irrelevant whether array is smi-only or not when writing a smi. |
707 __ movq(FieldOperand(rbx, rcx, times_pointer_size, FixedArray::kHeaderSize), | 707 __ movq(FieldOperand(rbx, rcx, times_pointer_size, FixedArray::kHeaderSize), |
708 rax); | 708 rax); |
709 __ ret(0); | 709 __ ret(0); |
710 | 710 |
711 __ bind(&non_smi_value); | 711 __ bind(&non_smi_value); |
712 // Writing a non-smi, check whether array allows non-smi elements. | 712 // Writing a non-smi, check whether array allows non-smi elements. |
713 // r9: receiver's map | 713 // r9: receiver's map |
714 __ CheckFastObjectElements(r9, &slow, Label::kNear); | 714 __ CheckFastObjectElements(r9, &slow, Label::kNear); |
715 __ lea(rcx, | 715 __ movq(FieldOperand(rbx, rcx, times_pointer_size, FixedArray::kHeaderSize), |
716 FieldOperand(rbx, rcx, times_pointer_size, FixedArray::kHeaderSize)); | 716 rax); |
717 __ movq(Operand(rcx, 0), rax); | 717 __ movq(rdx, rax); // Preserve the value which is returned. |
718 __ movq(rdx, rax); | 718 __ RecordWriteArray( |
719 __ RecordWrite( | 719 rbx, rdx, rcx, kDontSaveFPRegs, EMIT_REMEMBERED_SET, OMIT_SMI_CHECK); |
720 rbx, rcx, rdx, kDontSaveFPRegs, EMIT_REMEMBERED_SET, OMIT_SMI_CHECK); | |
721 __ ret(0); | 720 __ ret(0); |
722 | 721 |
723 __ bind(&fast_double_with_map_check); | 722 __ bind(&fast_double_with_map_check); |
724 // Check for fast double array case. If this fails, call through to the | 723 // Check for fast double array case. If this fails, call through to the |
725 // runtime. | 724 // runtime. |
726 // rdi: elements array's map | 725 // rdi: elements array's map |
727 __ CompareRoot(rdi, Heap::kFixedDoubleArrayMapRootIndex); | 726 __ CompareRoot(rdi, Heap::kFixedDoubleArrayMapRootIndex); |
728 __ j(not_equal, &slow); | 727 __ j(not_equal, &slow); |
729 __ bind(&fast_double_without_map_check); | 728 __ bind(&fast_double_without_map_check); |
730 // If the value is a number, store it as a double in the FastDoubleElements | 729 // If the value is a number, store it as a double in the FastDoubleElements |
731 // array. | 730 // array. |
732 __ StoreNumberToDoubleElements(rax, rbx, rcx, xmm0, &slow); | 731 __ StoreNumberToDoubleElements(rax, rbx, rcx, xmm0, &slow); |
733 __ ret(0); | 732 __ ret(0); |
734 } | 733 } |
735 | 734 |
736 | 735 |
737 // The generated code does not accept smi keys. | 736 // The generated code does not accept smi keys. |
738 // The generated code falls through if both probes miss. | 737 // The generated code falls through if both probes miss. |
739 static void GenerateMonomorphicCacheProbe(MacroAssembler* masm, | 738 void CallICBase::GenerateMonomorphicCacheProbe(MacroAssembler* masm, |
740 int argc, | 739 int argc, |
741 Code::Kind kind, | 740 Code::Kind kind, |
742 Code::ExtraICState extra_ic_state) { | 741 Code::ExtraICState extra_state) { |
743 // ----------- S t a t e ------------- | 742 // ----------- S t a t e ------------- |
744 // rcx : function name | 743 // rcx : function name |
745 // rdx : receiver | 744 // rdx : receiver |
746 // ----------------------------------- | 745 // ----------------------------------- |
747 Label number, non_number, non_string, boolean, probe, miss; | 746 Label number, non_number, non_string, boolean, probe, miss; |
748 | 747 |
749 // Probe the stub cache. | 748 // Probe the stub cache. |
750 Code::Flags flags = Code::ComputeFlags(kind, | 749 Code::Flags flags = Code::ComputeFlags(kind, |
751 MONOMORPHIC, | 750 MONOMORPHIC, |
752 extra_ic_state, | 751 extra_state, |
753 NORMAL, | 752 NORMAL, |
754 argc); | 753 argc); |
755 Isolate::Current()->stub_cache()->GenerateProbe(masm, flags, rdx, rcx, rbx, | 754 Isolate::Current()->stub_cache()->GenerateProbe(masm, flags, rdx, rcx, rbx, |
756 rax); | 755 rax); |
757 | 756 |
758 // If the stub cache probing failed, the receiver might be a value. | 757 // If the stub cache probing failed, the receiver might be a value. |
759 // For value objects, we use the map of the prototype objects for | 758 // For value objects, we use the map of the prototype objects for |
760 // the corresponding JSValue for the cache and that is what we need | 759 // the corresponding JSValue for the cache and that is what we need |
761 // to probe. | 760 // to probe. |
762 // | 761 // |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
815 __ j(not_equal, miss); | 814 __ j(not_equal, miss); |
816 | 815 |
817 // Invoke the function. | 816 // Invoke the function. |
818 ParameterCount actual(argc); | 817 ParameterCount actual(argc); |
819 __ InvokeFunction(rdi, actual, JUMP_FUNCTION, | 818 __ InvokeFunction(rdi, actual, JUMP_FUNCTION, |
820 NullCallWrapper(), CALL_AS_METHOD); | 819 NullCallWrapper(), CALL_AS_METHOD); |
821 } | 820 } |
822 | 821 |
823 | 822 |
824 // The generated code falls through if the call should be handled by runtime. | 823 // The generated code falls through if the call should be handled by runtime. |
825 static void GenerateCallNormal(MacroAssembler* masm, int argc) { | 824 void CallICBase::GenerateNormal(MacroAssembler* masm, int argc) { |
826 // ----------- S t a t e ------------- | 825 // ----------- S t a t e ------------- |
827 // rcx : function name | 826 // rcx : function name |
828 // rsp[0] : return address | 827 // rsp[0] : return address |
829 // rsp[8] : argument argc | 828 // rsp[8] : argument argc |
830 // rsp[16] : argument argc - 1 | 829 // rsp[16] : argument argc - 1 |
831 // ... | 830 // ... |
832 // rsp[argc * 8] : argument 1 | 831 // rsp[argc * 8] : argument 1 |
833 // rsp[(argc + 1) * 8] : argument 0 = receiver | 832 // rsp[(argc + 1) * 8] : argument 0 = receiver |
834 // ----------------------------------- | 833 // ----------------------------------- |
835 Label miss; | 834 Label miss; |
836 | 835 |
837 // Get the receiver of the function from the stack. | 836 // Get the receiver of the function from the stack. |
838 __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize)); | 837 __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize)); |
839 | 838 |
840 GenerateStringDictionaryReceiverCheck(masm, rdx, rax, rbx, &miss); | 839 GenerateStringDictionaryReceiverCheck(masm, rdx, rax, rbx, &miss); |
841 | 840 |
842 // rax: elements | 841 // rax: elements |
843 // Search the dictionary placing the result in rdi. | 842 // Search the dictionary placing the result in rdi. |
844 GenerateDictionaryLoad(masm, &miss, rax, rcx, rbx, rdi, rdi); | 843 GenerateDictionaryLoad(masm, &miss, rax, rcx, rbx, rdi, rdi); |
845 | 844 |
846 GenerateFunctionTailCall(masm, argc, &miss); | 845 GenerateFunctionTailCall(masm, argc, &miss); |
847 | 846 |
848 __ bind(&miss); | 847 __ bind(&miss); |
849 } | 848 } |
850 | 849 |
851 | 850 |
852 static void GenerateCallMiss(MacroAssembler* masm, | 851 void CallICBase::GenerateMiss(MacroAssembler* masm, |
853 int argc, | 852 int argc, |
854 IC::UtilityId id, | 853 IC::UtilityId id, |
855 Code::ExtraICState extra_ic_state) { | 854 Code::ExtraICState extra_state) { |
856 // ----------- S t a t e ------------- | 855 // ----------- S t a t e ------------- |
857 // rcx : function name | 856 // rcx : function name |
858 // rsp[0] : return address | 857 // rsp[0] : return address |
859 // rsp[8] : argument argc | 858 // rsp[8] : argument argc |
860 // rsp[16] : argument argc - 1 | 859 // rsp[16] : argument argc - 1 |
861 // ... | 860 // ... |
862 // rsp[argc * 8] : argument 1 | 861 // rsp[argc * 8] : argument 1 |
863 // rsp[(argc + 1) * 8] : argument 0 = receiver | 862 // rsp[(argc + 1) * 8] : argument 0 = receiver |
864 // ----------------------------------- | 863 // ----------------------------------- |
865 | 864 |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
903 __ j(not_equal, &invoke); | 902 __ j(not_equal, &invoke); |
904 | 903 |
905 // Patch the receiver on the stack. | 904 // Patch the receiver on the stack. |
906 __ bind(&global); | 905 __ bind(&global); |
907 __ movq(rdx, FieldOperand(rdx, GlobalObject::kGlobalReceiverOffset)); | 906 __ movq(rdx, FieldOperand(rdx, GlobalObject::kGlobalReceiverOffset)); |
908 __ movq(Operand(rsp, (argc + 1) * kPointerSize), rdx); | 907 __ movq(Operand(rsp, (argc + 1) * kPointerSize), rdx); |
909 __ bind(&invoke); | 908 __ bind(&invoke); |
910 } | 909 } |
911 | 910 |
912 // Invoke the function. | 911 // Invoke the function. |
913 CallKind call_kind = CallICBase::Contextual::decode(extra_ic_state) | 912 CallKind call_kind = CallICBase::Contextual::decode(extra_state) |
914 ? CALL_AS_FUNCTION | 913 ? CALL_AS_FUNCTION |
915 : CALL_AS_METHOD; | 914 : CALL_AS_METHOD; |
916 ParameterCount actual(argc); | 915 ParameterCount actual(argc); |
917 __ InvokeFunction(rdi, | 916 __ InvokeFunction(rdi, |
918 actual, | 917 actual, |
919 JUMP_FUNCTION, | 918 JUMP_FUNCTION, |
920 NullCallWrapper(), | 919 NullCallWrapper(), |
921 call_kind); | 920 call_kind); |
922 } | 921 } |
923 | 922 |
(...skipping 11 matching lines...) Expand all Loading... |
935 // rsp[(argc + 1) * 8] : argument 0 = receiver | 934 // rsp[(argc + 1) * 8] : argument 0 = receiver |
936 // ----------------------------------- | 935 // ----------------------------------- |
937 | 936 |
938 // Get the receiver of the function from the stack; 1 ~ return address. | 937 // Get the receiver of the function from the stack; 1 ~ return address. |
939 __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize)); | 938 __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize)); |
940 GenerateMonomorphicCacheProbe(masm, argc, Code::CALL_IC, extra_ic_state); | 939 GenerateMonomorphicCacheProbe(masm, argc, Code::CALL_IC, extra_ic_state); |
941 GenerateMiss(masm, argc, extra_ic_state); | 940 GenerateMiss(masm, argc, extra_ic_state); |
942 } | 941 } |
943 | 942 |
944 | 943 |
945 void CallIC::GenerateNormal(MacroAssembler* masm, int argc) { | |
946 // ----------- S t a t e ------------- | |
947 // rcx : function name | |
948 // rsp[0] : return address | |
949 // rsp[8] : argument argc | |
950 // rsp[16] : argument argc - 1 | |
951 // ... | |
952 // rsp[argc * 8] : argument 1 | |
953 // rsp[(argc + 1) * 8] : argument 0 = receiver | |
954 // ----------------------------------- | |
955 | |
956 GenerateCallNormal(masm, argc); | |
957 GenerateMiss(masm, argc, Code::kNoExtraICState); | |
958 } | |
959 | |
960 | |
961 void CallIC::GenerateMiss(MacroAssembler* masm, | |
962 int argc, | |
963 Code::ExtraICState extra_ic_state) { | |
964 // ----------- S t a t e ------------- | |
965 // rcx : function name | |
966 // rsp[0] : return address | |
967 // rsp[8] : argument argc | |
968 // rsp[16] : argument argc - 1 | |
969 // ... | |
970 // rsp[argc * 8] : argument 1 | |
971 // rsp[(argc + 1) * 8] : argument 0 = receiver | |
972 // ----------------------------------- | |
973 | |
974 GenerateCallMiss(masm, argc, IC::kCallIC_Miss, extra_ic_state); | |
975 } | |
976 | |
977 | |
978 void KeyedCallIC::GenerateMegamorphic(MacroAssembler* masm, int argc) { | 944 void KeyedCallIC::GenerateMegamorphic(MacroAssembler* masm, int argc) { |
979 // ----------- S t a t e ------------- | 945 // ----------- S t a t e ------------- |
980 // rcx : function name | 946 // rcx : function name |
981 // rsp[0] : return address | 947 // rsp[0] : return address |
982 // rsp[8] : argument argc | 948 // rsp[8] : argument argc |
983 // rsp[16] : argument argc - 1 | 949 // rsp[16] : argument argc - 1 |
984 // ... | 950 // ... |
985 // rsp[argc * 8] : argument 1 | 951 // rsp[argc * 8] : argument 1 |
986 // rsp[(argc + 1) * 8] : argument 0 = receiver | 952 // rsp[(argc + 1) * 8] : argument 0 = receiver |
987 // ----------------------------------- | 953 // ----------------------------------- |
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1095 // ... | 1061 // ... |
1096 // rsp[argc * 8] : argument 1 | 1062 // rsp[argc * 8] : argument 1 |
1097 // rsp[(argc + 1) * 8] : argument 0 = receiver | 1063 // rsp[(argc + 1) * 8] : argument 0 = receiver |
1098 // ----------------------------------- | 1064 // ----------------------------------- |
1099 | 1065 |
1100 // Check if the name is a string. | 1066 // Check if the name is a string. |
1101 Label miss; | 1067 Label miss; |
1102 __ JumpIfSmi(rcx, &miss); | 1068 __ JumpIfSmi(rcx, &miss); |
1103 Condition cond = masm->IsObjectStringType(rcx, rax, rax); | 1069 Condition cond = masm->IsObjectStringType(rcx, rax, rax); |
1104 __ j(NegateCondition(cond), &miss); | 1070 __ j(NegateCondition(cond), &miss); |
1105 GenerateCallNormal(masm, argc); | 1071 CallICBase::GenerateNormal(masm, argc); |
1106 __ bind(&miss); | 1072 __ bind(&miss); |
1107 GenerateMiss(masm, argc); | 1073 GenerateMiss(masm, argc); |
1108 } | 1074 } |
1109 | 1075 |
1110 | 1076 |
1111 void KeyedCallIC::GenerateMiss(MacroAssembler* masm, int argc) { | |
1112 // ----------- S t a t e ------------- | |
1113 // rcx : function name | |
1114 // rsp[0] : return address | |
1115 // rsp[8] : argument argc | |
1116 // rsp[16] : argument argc - 1 | |
1117 // ... | |
1118 // rsp[argc * 8] : argument 1 | |
1119 // rsp[(argc + 1) * 8] : argument 0 = receiver | |
1120 // ----------------------------------- | |
1121 | |
1122 GenerateCallMiss(masm, argc, IC::kKeyedCallIC_Miss, Code::kNoExtraICState); | |
1123 } | |
1124 | |
1125 | |
1126 static Operand GenerateMappedArgumentsLookup(MacroAssembler* masm, | 1077 static Operand GenerateMappedArgumentsLookup(MacroAssembler* masm, |
1127 Register object, | 1078 Register object, |
1128 Register key, | 1079 Register key, |
1129 Register scratch1, | 1080 Register scratch1, |
1130 Register scratch2, | 1081 Register scratch2, |
1131 Register scratch3, | 1082 Register scratch3, |
1132 Label* unmapped_case, | 1083 Label* unmapped_case, |
1133 Label* slow_case) { | 1084 Label* slow_case) { |
1134 Heap* heap = masm->isolate()->heap(); | 1085 Heap* heap = masm->isolate()->heap(); |
1135 | 1086 |
(...skipping 459 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1595 | 1546 |
1596 // Do tail-call to runtime routine. | 1547 // Do tail-call to runtime routine. |
1597 ExternalReference ref = force_generic | 1548 ExternalReference ref = force_generic |
1598 ? ExternalReference(IC_Utility(kKeyedStoreIC_MissForceGeneric), | 1549 ? ExternalReference(IC_Utility(kKeyedStoreIC_MissForceGeneric), |
1599 masm->isolate()) | 1550 masm->isolate()) |
1600 : ExternalReference(IC_Utility(kKeyedStoreIC_Miss), masm->isolate()); | 1551 : ExternalReference(IC_Utility(kKeyedStoreIC_Miss), masm->isolate()); |
1601 __ TailCallExternalReference(ref, 3, 1); | 1552 __ TailCallExternalReference(ref, 3, 1); |
1602 } | 1553 } |
1603 | 1554 |
1604 | 1555 |
| 1556 void KeyedStoreIC::GenerateTransitionElementsSmiToDouble(MacroAssembler* masm) { |
| 1557 // ----------- S t a t e ------------- |
| 1558 // -- rbx : target map |
| 1559 // -- rdx : receiver |
| 1560 // -- rsp[0] : return address |
| 1561 // ----------------------------------- |
| 1562 // Must return the modified receiver in eax. |
| 1563 if (!FLAG_trace_elements_transitions) { |
| 1564 Label fail; |
| 1565 ElementsTransitionGenerator::GenerateSmiOnlyToDouble(masm, &fail); |
| 1566 __ movq(rax, rdx); |
| 1567 __ Ret(); |
| 1568 __ bind(&fail); |
| 1569 } |
| 1570 |
| 1571 __ pop(rbx); |
| 1572 __ push(rdx); |
| 1573 __ push(rbx); // return address |
| 1574 __ TailCallRuntime(Runtime::kTransitionElementsSmiToDouble, 1, 1); |
| 1575 } |
| 1576 |
| 1577 |
| 1578 void KeyedStoreIC::GenerateTransitionElementsDoubleToObject( |
| 1579 MacroAssembler* masm) { |
| 1580 // ----------- S t a t e ------------- |
| 1581 // -- rbx : target map |
| 1582 // -- rdx : receiver |
| 1583 // -- rsp[0] : return address |
| 1584 // ----------------------------------- |
| 1585 // Must return the modified receiver in eax. |
| 1586 if (!FLAG_trace_elements_transitions) { |
| 1587 Label fail; |
| 1588 ElementsTransitionGenerator::GenerateDoubleToObject(masm, &fail); |
| 1589 __ movq(rax, rdx); |
| 1590 __ Ret(); |
| 1591 __ bind(&fail); |
| 1592 } |
| 1593 |
| 1594 __ pop(rbx); |
| 1595 __ push(rdx); |
| 1596 __ push(rbx); // return address |
| 1597 __ TailCallRuntime(Runtime::kTransitionElementsDoubleToObject, 1, 1); |
| 1598 } |
| 1599 |
| 1600 |
1605 #undef __ | 1601 #undef __ |
1606 | 1602 |
1607 | 1603 |
1608 Condition CompareIC::ComputeCondition(Token::Value op) { | 1604 Condition CompareIC::ComputeCondition(Token::Value op) { |
1609 switch (op) { | 1605 switch (op) { |
1610 case Token::EQ_STRICT: | 1606 case Token::EQ_STRICT: |
1611 case Token::EQ: | 1607 case Token::EQ: |
1612 return equal; | 1608 return equal; |
1613 case Token::LT: | 1609 case Token::LT: |
1614 return less; | 1610 return less; |
1615 case Token::GT: | 1611 case Token::GT: |
1616 // Reverse left and right operands to obtain ECMA-262 conversion order. | 1612 return greater; |
1617 return less; | |
1618 case Token::LTE: | 1613 case Token::LTE: |
1619 // Reverse left and right operands to obtain ECMA-262 conversion order. | 1614 return less_equal; |
1620 return greater_equal; | |
1621 case Token::GTE: | 1615 case Token::GTE: |
1622 return greater_equal; | 1616 return greater_equal; |
1623 default: | 1617 default: |
1624 UNREACHABLE(); | 1618 UNREACHABLE(); |
1625 return no_condition; | 1619 return no_condition; |
1626 } | 1620 } |
1627 } | 1621 } |
1628 | 1622 |
1629 | 1623 |
1630 static bool HasInlinedSmiCode(Address address) { | 1624 static bool HasInlinedSmiCode(Address address) { |
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1697 Condition cc = *jmp_address == Assembler::kJncShortOpcode | 1691 Condition cc = *jmp_address == Assembler::kJncShortOpcode |
1698 ? not_zero | 1692 ? not_zero |
1699 : zero; | 1693 : zero; |
1700 *jmp_address = static_cast<byte>(Assembler::kJccShortPrefix | cc); | 1694 *jmp_address = static_cast<byte>(Assembler::kJccShortPrefix | cc); |
1701 } | 1695 } |
1702 | 1696 |
1703 | 1697 |
1704 } } // namespace v8::internal | 1698 } } // namespace v8::internal |
1705 | 1699 |
1706 #endif // V8_TARGET_ARCH_X64 | 1700 #endif // V8_TARGET_ARCH_X64 |
OLD | NEW |