OLD | NEW |
1 // Copyright 2010 the V8 project authors. All rights reserved. | 1 // Copyright 2010 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 684 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
695 } | 695 } |
696 | 696 |
697 | 697 |
698 void KeyedLoadIC::GenerateExternalArray(MacroAssembler* masm, | 698 void KeyedLoadIC::GenerateExternalArray(MacroAssembler* masm, |
699 ExternalArrayType array_type) { | 699 ExternalArrayType array_type) { |
700 // ----------- S t a t e ------------- | 700 // ----------- S t a t e ------------- |
701 // -- rax : key | 701 // -- rax : key |
702 // -- rdx : receiver | 702 // -- rdx : receiver |
703 // -- rsp[0] : return address | 703 // -- rsp[0] : return address |
704 // ----------------------------------- | 704 // ----------------------------------- |
705 Label slow, failed_allocation; | 705 Label slow; |
706 | 706 |
707 // Check that the object isn't a smi. | 707 // Check that the object isn't a smi. |
708 __ JumpIfSmi(rdx, &slow); | 708 __ JumpIfSmi(rdx, &slow); |
709 | 709 |
710 // Check that the key is a smi. | 710 // Check that the key is a smi. |
711 __ JumpIfNotSmi(rax, &slow); | 711 __ JumpIfNotSmi(rax, &slow); |
712 | 712 |
713 // Check that the object is a JS object. | 713 // Check that the object is a JS object. |
714 __ CmpObjectType(rdx, JS_OBJECT_TYPE, rcx); | 714 __ CmpObjectType(rdx, JS_OBJECT_TYPE, rcx); |
715 __ j(not_equal, &slow); | 715 __ j(not_equal, &slow); |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
754 case kExternalUnsignedShortArray: | 754 case kExternalUnsignedShortArray: |
755 __ movzxwq(rcx, Operand(rbx, rcx, times_2, 0)); | 755 __ movzxwq(rcx, Operand(rbx, rcx, times_2, 0)); |
756 break; | 756 break; |
757 case kExternalIntArray: | 757 case kExternalIntArray: |
758 __ movsxlq(rcx, Operand(rbx, rcx, times_4, 0)); | 758 __ movsxlq(rcx, Operand(rbx, rcx, times_4, 0)); |
759 break; | 759 break; |
760 case kExternalUnsignedIntArray: | 760 case kExternalUnsignedIntArray: |
761 __ movl(rcx, Operand(rbx, rcx, times_4, 0)); | 761 __ movl(rcx, Operand(rbx, rcx, times_4, 0)); |
762 break; | 762 break; |
763 case kExternalFloatArray: | 763 case kExternalFloatArray: |
764 __ fld_s(Operand(rbx, rcx, times_4, 0)); | 764 __ cvtss2sd(xmm0, Operand(rbx, rcx, times_4, 0)); |
765 break; | 765 break; |
766 default: | 766 default: |
767 UNREACHABLE(); | 767 UNREACHABLE(); |
768 break; | 768 break; |
769 } | 769 } |
770 | 770 |
771 // rax: index | 771 // rax: index |
772 // rdx: receiver | 772 // rdx: receiver |
773 // For integer array types: | 773 // For integer array types: |
774 // rcx: value | 774 // rcx: value |
775 // For floating-point array type: | 775 // For floating-point array type: |
776 // FP(0): value | 776 // xmm0: value as double. |
777 | 777 |
778 if (array_type == kExternalIntArray || | 778 ASSERT(kSmiValueSize == 32); |
779 array_type == kExternalUnsignedIntArray) { | 779 if (array_type == kExternalUnsignedIntArray) { |
780 // For the Int and UnsignedInt array types, we need to see whether | 780 // For the UnsignedInt array type, we need to see whether |
781 // the value can be represented in a Smi. If not, we need to convert | 781 // the value can be represented in a Smi. If not, we need to convert |
782 // it to a HeapNumber. | 782 // it to a HeapNumber. |
783 Label box_int; | 783 Label box_int; |
784 if (array_type == kExternalIntArray) { | 784 |
785 __ JumpIfNotValidSmiValue(rcx, &box_int); | 785 __ JumpIfUIntNotValidSmiValue(rcx, &box_int); |
786 } else { | |
787 ASSERT_EQ(array_type, kExternalUnsignedIntArray); | |
788 __ JumpIfUIntNotValidSmiValue(rcx, &box_int); | |
789 } | |
790 | 786 |
791 __ Integer32ToSmi(rax, rcx); | 787 __ Integer32ToSmi(rax, rcx); |
792 __ ret(0); | 788 __ ret(0); |
793 | 789 |
794 __ bind(&box_int); | 790 __ bind(&box_int); |
795 | 791 |
796 // Allocate a HeapNumber for the int and perform int-to-double | 792 // Allocate a HeapNumber for the int and perform int-to-double |
797 // conversion. | 793 // conversion. |
798 __ push(rcx); | 794 ASSERT(array_type == kExternalUnsignedIntArray); |
799 if (array_type == kExternalIntArray) { | 795 // The value is zero-extended since we loaded the value from memory |
800 __ fild_s(Operand(rsp, 0)); | 796 // with movl. |
801 } else { | 797 __ cvtqsi2sd(xmm0, rcx); |
802 ASSERT(array_type == kExternalUnsignedIntArray); | 798 |
803 // The value is zero-extended on the stack, because all pushes are | 799 __ AllocateHeapNumber(rcx, rbx, &slow); |
804 // 64-bit and we loaded the value from memory with movl. | |
805 __ fild_d(Operand(rsp, 0)); | |
806 } | |
807 __ pop(rcx); | |
808 // FP(0): value | |
809 __ AllocateHeapNumber(rcx, rbx, &failed_allocation); | |
810 // Set the value. | 800 // Set the value. |
| 801 __ movsd(FieldOperand(rcx, HeapNumber::kValueOffset), xmm0); |
811 __ movq(rax, rcx); | 802 __ movq(rax, rcx); |
812 __ fstp_d(FieldOperand(rax, HeapNumber::kValueOffset)); | |
813 __ ret(0); | 803 __ ret(0); |
814 } else if (array_type == kExternalFloatArray) { | 804 } else if (array_type == kExternalFloatArray) { |
815 // For the floating-point array type, we need to always allocate a | 805 // For the floating-point array type, we need to always allocate a |
816 // HeapNumber. | 806 // HeapNumber. |
817 __ AllocateHeapNumber(rcx, rbx, &failed_allocation); | 807 __ AllocateHeapNumber(rcx, rbx, &slow); |
818 // Set the value. | 808 // Set the value. |
| 809 __ movsd(FieldOperand(rcx, HeapNumber::kValueOffset), xmm0); |
819 __ movq(rax, rcx); | 810 __ movq(rax, rcx); |
820 __ fstp_d(FieldOperand(rax, HeapNumber::kValueOffset)); | |
821 __ ret(0); | 811 __ ret(0); |
822 } else { | 812 } else { |
823 __ Integer32ToSmi(rax, rcx); | 813 __ Integer32ToSmi(rax, rcx); |
824 __ ret(0); | 814 __ ret(0); |
825 } | 815 } |
826 | 816 |
827 // If we fail allocation of the HeapNumber, we still have a value on | |
828 // top of the FPU stack. Remove it. | |
829 __ bind(&failed_allocation); | |
830 __ ffree(); | |
831 __ fincstp(); | |
832 // Fall through to slow case. | |
833 | |
834 // Slow case: Jump to runtime. | 817 // Slow case: Jump to runtime. |
835 __ bind(&slow); | 818 __ bind(&slow); |
836 __ IncrementCounter(&Counters::keyed_load_external_array_slow, 1); | 819 __ IncrementCounter(&Counters::keyed_load_external_array_slow, 1); |
837 GenerateRuntimeGetProperty(masm); | 820 GenerateRuntimeGetProperty(masm); |
838 } | 821 } |
839 | 822 |
840 | 823 |
841 void KeyedLoadIC::GenerateIndexedInterceptor(MacroAssembler* masm) { | 824 void KeyedLoadIC::GenerateIndexedInterceptor(MacroAssembler* masm) { |
842 // ----------- S t a t e ------------- | 825 // ----------- S t a t e ------------- |
843 // -- rax : key | 826 // -- rax : key |
(...skipping 265 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1109 case kExternalShortArray: | 1092 case kExternalShortArray: |
1110 case kExternalUnsignedShortArray: | 1093 case kExternalUnsignedShortArray: |
1111 __ movw(Operand(rbx, rdi, times_2, 0), rdx); | 1094 __ movw(Operand(rbx, rdi, times_2, 0), rdx); |
1112 break; | 1095 break; |
1113 case kExternalIntArray: | 1096 case kExternalIntArray: |
1114 case kExternalUnsignedIntArray: | 1097 case kExternalUnsignedIntArray: |
1115 __ movl(Operand(rbx, rdi, times_4, 0), rdx); | 1098 __ movl(Operand(rbx, rdi, times_4, 0), rdx); |
1116 break; | 1099 break; |
1117 case kExternalFloatArray: | 1100 case kExternalFloatArray: |
1118 // Need to perform int-to-float conversion. | 1101 // Need to perform int-to-float conversion. |
1119 __ push(rdx); | 1102 __ cvtlsi2ss(xmm0, rdx); |
1120 __ fild_s(Operand(rsp, 0)); | 1103 __ movss(Operand(rbx, rdi, times_4, 0), xmm0); |
1121 __ pop(rdx); | |
1122 __ fstp_s(Operand(rbx, rdi, times_4, 0)); | |
1123 break; | 1104 break; |
1124 default: | 1105 default: |
1125 UNREACHABLE(); | 1106 UNREACHABLE(); |
1126 break; | 1107 break; |
1127 } | 1108 } |
1128 __ ret(0); | 1109 __ ret(0); |
1129 | 1110 |
1130 __ bind(&check_heap_number); | 1111 __ bind(&check_heap_number); |
1131 // rax: value | 1112 // rax: value |
1132 // rcx: key (a smi) | 1113 // rcx: key (a smi) |
(...skipping 16 matching lines...) Expand all Loading... |
1149 __ fstp_s(Operand(rbx, rdi, times_4, 0)); | 1130 __ fstp_s(Operand(rbx, rdi, times_4, 0)); |
1150 __ ret(0); | 1131 __ ret(0); |
1151 } else { | 1132 } else { |
1152 // Need to perform float-to-int conversion. | 1133 // Need to perform float-to-int conversion. |
1153 // Test the top of the FP stack for NaN. | 1134 // Test the top of the FP stack for NaN. |
1154 Label is_nan; | 1135 Label is_nan; |
1155 __ fucomi(0); | 1136 __ fucomi(0); |
1156 __ j(parity_even, &is_nan); | 1137 __ j(parity_even, &is_nan); |
1157 | 1138 |
1158 __ push(rdx); // Make room on the stack. Receiver is no longer needed. | 1139 __ push(rdx); // Make room on the stack. Receiver is no longer needed. |
| 1140 // TODO(lrn): If the rounding of this conversion is not deliberate, maybe |
| 1141 // switch to xmm registers. |
1159 __ fistp_d(Operand(rsp, 0)); | 1142 __ fistp_d(Operand(rsp, 0)); |
1160 __ pop(rdx); | 1143 __ pop(rdx); |
1161 // rdx: value (converted to an untagged integer) | 1144 // rdx: value (converted to an untagged integer) |
1162 // rdi: untagged index | 1145 // rdi: untagged index |
1163 // rbx: base pointer of external storage | 1146 // rbx: base pointer of external storage |
1164 switch (array_type) { | 1147 switch (array_type) { |
1165 case kExternalByteArray: | 1148 case kExternalByteArray: |
1166 case kExternalUnsignedByteArray: | 1149 case kExternalUnsignedByteArray: |
1167 __ movb(Operand(rbx, rdi, times_1, 0), rdx); | 1150 __ movb(Operand(rbx, rdi, times_1, 0), rdx); |
1168 break; | 1151 break; |
(...skipping 25 matching lines...) Expand all Loading... |
1194 UNREACHABLE(); | 1177 UNREACHABLE(); |
1195 break; | 1178 break; |
1196 } | 1179 } |
1197 __ ret(0); | 1180 __ ret(0); |
1198 | 1181 |
1199 __ bind(&is_nan); | 1182 __ bind(&is_nan); |
1200 // rdi: untagged index | 1183 // rdi: untagged index |
1201 // rbx: base pointer of external storage | 1184 // rbx: base pointer of external storage |
1202 __ ffree(); | 1185 __ ffree(); |
1203 __ fincstp(); | 1186 __ fincstp(); |
1204 __ movq(rdx, Immediate(0)); | 1187 __ Set(rdx, 0); |
1205 switch (array_type) { | 1188 switch (array_type) { |
1206 case kExternalByteArray: | 1189 case kExternalByteArray: |
1207 case kExternalUnsignedByteArray: | 1190 case kExternalUnsignedByteArray: |
1208 __ movb(Operand(rbx, rdi, times_1, 0), rdx); | 1191 __ movb(Operand(rbx, rdi, times_1, 0), rdx); |
1209 break; | 1192 break; |
1210 case kExternalShortArray: | 1193 case kExternalShortArray: |
1211 case kExternalUnsignedShortArray: | 1194 case kExternalUnsignedShortArray: |
1212 __ movw(Operand(rbx, rdi, times_2, 0), rdx); | 1195 __ movw(Operand(rbx, rdi, times_2, 0), rdx); |
1213 break; | 1196 break; |
1214 case kExternalIntArray: | 1197 case kExternalIntArray: |
(...skipping 601 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1816 GenerateMiss(masm); | 1799 GenerateMiss(masm); |
1817 } | 1800 } |
1818 | 1801 |
1819 | 1802 |
1820 #undef __ | 1803 #undef __ |
1821 | 1804 |
1822 | 1805 |
1823 } } // namespace v8::internal | 1806 } } // namespace v8::internal |
1824 | 1807 |
1825 #endif // V8_TARGET_ARCH_X64 | 1808 #endif // V8_TARGET_ARCH_X64 |
OLD | NEW |