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