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 745 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
756 // overflowed the smi range). | 756 // overflowed the smi range). |
757 switch (op_) { | 757 switch (op_) { |
758 case Token::SHL: { | 758 case Token::SHL: { |
759 Comment perform_float(masm, "-- Perform float operation on smis"); | 759 Comment perform_float(masm, "-- Perform float operation on smis"); |
760 __ bind(&use_fp_on_smis); | 760 __ bind(&use_fp_on_smis); |
761 if (runtime_operands_type_ != BinaryOpIC::UNINIT_OR_SMI) { | 761 if (runtime_operands_type_ != BinaryOpIC::UNINIT_OR_SMI) { |
762 // Result we want is in left == edx, so we can put the allocated heap | 762 // Result we want is in left == edx, so we can put the allocated heap |
763 // number in eax. | 763 // number in eax. |
764 __ AllocateHeapNumber(eax, ecx, ebx, slow); | 764 __ AllocateHeapNumber(eax, ecx, ebx, slow); |
765 // Store the result in the HeapNumber and return. | 765 // Store the result in the HeapNumber and return. |
766 if (Isolate::Current()->cpu_features()->IsSupported(SSE2)) { | 766 if (masm->isolate()->cpu_features()->IsSupported(SSE2)) { |
767 CpuFeatures::Scope use_sse2(SSE2); | 767 CpuFeatures::Scope use_sse2(SSE2); |
768 __ cvtsi2sd(xmm0, Operand(left)); | 768 __ cvtsi2sd(xmm0, Operand(left)); |
769 __ movdbl(FieldOperand(eax, HeapNumber::kValueOffset), xmm0); | 769 __ movdbl(FieldOperand(eax, HeapNumber::kValueOffset), xmm0); |
770 } else { | 770 } else { |
771 // It's OK to overwrite the right argument on the stack because we | 771 // It's OK to overwrite the right argument on the stack because we |
772 // are about to return. | 772 // are about to return. |
773 __ mov(Operand(esp, 1 * kPointerSize), left); | 773 __ mov(Operand(esp, 1 * kPointerSize), left); |
774 __ fild_s(Operand(esp, 1 * kPointerSize)); | 774 __ fild_s(Operand(esp, 1 * kPointerSize)); |
775 __ fstp_d(FieldOperand(eax, HeapNumber::kValueOffset)); | 775 __ fstp_d(FieldOperand(eax, HeapNumber::kValueOffset)); |
776 } | 776 } |
(...skipping 29 matching lines...) Expand all Loading... |
806 // Left was clobbered but a copy is in edi. Right is in ebx for | 806 // Left was clobbered but a copy is in edi. Right is in ebx for |
807 // division. | 807 // division. |
808 __ mov(edx, edi); | 808 __ mov(edx, edi); |
809 __ mov(eax, right); | 809 __ mov(eax, right); |
810 break; | 810 break; |
811 default: UNREACHABLE(); | 811 default: UNREACHABLE(); |
812 break; | 812 break; |
813 } | 813 } |
814 if (runtime_operands_type_ != BinaryOpIC::UNINIT_OR_SMI) { | 814 if (runtime_operands_type_ != BinaryOpIC::UNINIT_OR_SMI) { |
815 __ AllocateHeapNumber(ecx, ebx, no_reg, slow); | 815 __ AllocateHeapNumber(ecx, ebx, no_reg, slow); |
816 if (Isolate::Current()->cpu_features()->IsSupported(SSE2)) { | 816 if (masm->isolate()->cpu_features()->IsSupported(SSE2)) { |
817 CpuFeatures::Scope use_sse2(SSE2); | 817 CpuFeatures::Scope use_sse2(SSE2); |
818 FloatingPointHelper::LoadSSE2Smis(masm, ebx); | 818 FloatingPointHelper::LoadSSE2Smis(masm, ebx); |
819 switch (op_) { | 819 switch (op_) { |
820 case Token::ADD: __ addsd(xmm0, xmm1); break; | 820 case Token::ADD: __ addsd(xmm0, xmm1); break; |
821 case Token::SUB: __ subsd(xmm0, xmm1); break; | 821 case Token::SUB: __ subsd(xmm0, xmm1); break; |
822 case Token::MUL: __ mulsd(xmm0, xmm1); break; | 822 case Token::MUL: __ mulsd(xmm0, xmm1); break; |
823 case Token::DIV: __ divsd(xmm0, xmm1); break; | 823 case Token::DIV: __ divsd(xmm0, xmm1); break; |
824 default: UNREACHABLE(); | 824 default: UNREACHABLE(); |
825 } | 825 } |
826 __ movdbl(FieldOperand(ecx, HeapNumber::kValueOffset), xmm0); | 826 __ movdbl(FieldOperand(ecx, HeapNumber::kValueOffset), xmm0); |
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
910 // Execution reaches this point when the first non-smi argument occurs | 910 // Execution reaches this point when the first non-smi argument occurs |
911 // (and only if smi code is generated). This is the right moment to | 911 // (and only if smi code is generated). This is the right moment to |
912 // patch to HEAP_NUMBERS state. The transition is attempted only for | 912 // patch to HEAP_NUMBERS state. The transition is attempted only for |
913 // the four basic operations. The stub stays in the DEFAULT state | 913 // the four basic operations. The stub stays in the DEFAULT state |
914 // forever for all other operations (also if smi code is skipped). | 914 // forever for all other operations (also if smi code is skipped). |
915 GenerateTypeTransition(masm); | 915 GenerateTypeTransition(masm); |
916 break; | 916 break; |
917 } | 917 } |
918 | 918 |
919 Label not_floats; | 919 Label not_floats; |
920 if (Isolate::Current()->cpu_features()->IsSupported(SSE2)) { | 920 if (masm->isolate()->cpu_features()->IsSupported(SSE2)) { |
921 CpuFeatures::Scope use_sse2(SSE2); | 921 CpuFeatures::Scope use_sse2(SSE2); |
922 if (static_operands_type_.IsNumber()) { | 922 if (static_operands_type_.IsNumber()) { |
923 if (FLAG_debug_code) { | 923 if (FLAG_debug_code) { |
924 // Assert at runtime that inputs are only numbers. | 924 // Assert at runtime that inputs are only numbers. |
925 __ AbortIfNotNumber(edx); | 925 __ AbortIfNotNumber(edx); |
926 __ AbortIfNotNumber(eax); | 926 __ AbortIfNotNumber(eax); |
927 } | 927 } |
928 if (static_operands_type_.IsSmi()) { | 928 if (static_operands_type_.IsSmi()) { |
929 if (FLAG_debug_code) { | 929 if (FLAG_debug_code) { |
930 __ AbortIfNotSmi(edx); | 930 __ AbortIfNotSmi(edx); |
(...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1044 __ test(eax, Immediate(kSmiTagMask)); | 1044 __ test(eax, Immediate(kSmiTagMask)); |
1045 __ j(not_zero, &skip_allocation, not_taken); | 1045 __ j(not_zero, &skip_allocation, not_taken); |
1046 // Fall through! | 1046 // Fall through! |
1047 case NO_OVERWRITE: | 1047 case NO_OVERWRITE: |
1048 __ AllocateHeapNumber(eax, ecx, edx, &call_runtime); | 1048 __ AllocateHeapNumber(eax, ecx, edx, &call_runtime); |
1049 __ bind(&skip_allocation); | 1049 __ bind(&skip_allocation); |
1050 break; | 1050 break; |
1051 default: UNREACHABLE(); | 1051 default: UNREACHABLE(); |
1052 } | 1052 } |
1053 // Store the result in the HeapNumber and return. | 1053 // Store the result in the HeapNumber and return. |
1054 if (Isolate::Current()->cpu_features()->IsSupported(SSE2)) { | 1054 if (masm->isolate()->cpu_features()->IsSupported(SSE2)) { |
1055 CpuFeatures::Scope use_sse2(SSE2); | 1055 CpuFeatures::Scope use_sse2(SSE2); |
1056 __ cvtsi2sd(xmm0, Operand(ebx)); | 1056 __ cvtsi2sd(xmm0, Operand(ebx)); |
1057 __ movdbl(FieldOperand(eax, HeapNumber::kValueOffset), xmm0); | 1057 __ movdbl(FieldOperand(eax, HeapNumber::kValueOffset), xmm0); |
1058 } else { | 1058 } else { |
1059 __ mov(Operand(esp, 1 * kPointerSize), ebx); | 1059 __ mov(Operand(esp, 1 * kPointerSize), ebx); |
1060 __ fild_s(Operand(esp, 1 * kPointerSize)); | 1060 __ fild_s(Operand(esp, 1 * kPointerSize)); |
1061 __ fstp_d(FieldOperand(eax, HeapNumber::kValueOffset)); | 1061 __ fstp_d(FieldOperand(eax, HeapNumber::kValueOffset)); |
1062 } | 1062 } |
1063 GenerateReturn(masm); | 1063 GenerateReturn(masm); |
1064 } | 1064 } |
(...skipping 197 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1262 // encoded into the key, the encoding is opaque, so push them too. | 1262 // encoded into the key, the encoding is opaque, so push them too. |
1263 __ push(Immediate(Smi::FromInt(MinorKey()))); | 1263 __ push(Immediate(Smi::FromInt(MinorKey()))); |
1264 __ push(Immediate(Smi::FromInt(op_))); | 1264 __ push(Immediate(Smi::FromInt(op_))); |
1265 __ push(Immediate(Smi::FromInt(runtime_operands_type_))); | 1265 __ push(Immediate(Smi::FromInt(runtime_operands_type_))); |
1266 | 1266 |
1267 __ push(ecx); // Push return address. | 1267 __ push(ecx); // Push return address. |
1268 | 1268 |
1269 // Patch the caller to an appropriate specialized stub and return the | 1269 // Patch the caller to an appropriate specialized stub and return the |
1270 // operation result to the caller of the stub. | 1270 // operation result to the caller of the stub. |
1271 __ TailCallExternalReference( | 1271 __ TailCallExternalReference( |
1272 ExternalReference(IC_Utility(IC::kBinaryOp_Patch)), | 1272 ExternalReference(IC_Utility(IC::kBinaryOp_Patch), masm->isolate()), |
1273 5, | 1273 5, |
1274 1); | 1274 1); |
1275 } | 1275 } |
1276 | 1276 |
1277 | 1277 |
1278 Handle<Code> GetBinaryOpStub(int key, BinaryOpIC::TypeInfo type_info) { | 1278 Handle<Code> GetBinaryOpStub(int key, BinaryOpIC::TypeInfo type_info) { |
1279 GenericBinaryOpStub stub(key, type_info); | 1279 GenericBinaryOpStub stub(key, type_info); |
1280 return stub.GetCode(); | 1280 return stub.GetCode(); |
1281 } | 1281 } |
1282 | 1282 |
(...skipping 15 matching lines...) Expand all Loading... |
1298 // encoded into the key, the encoding is opaque, so push them too. | 1298 // encoded into the key, the encoding is opaque, so push them too. |
1299 __ push(Immediate(Smi::FromInt(MinorKey()))); | 1299 __ push(Immediate(Smi::FromInt(MinorKey()))); |
1300 __ push(Immediate(Smi::FromInt(op_))); | 1300 __ push(Immediate(Smi::FromInt(op_))); |
1301 __ push(Immediate(Smi::FromInt(operands_type_))); | 1301 __ push(Immediate(Smi::FromInt(operands_type_))); |
1302 | 1302 |
1303 __ push(ecx); // Push return address. | 1303 __ push(ecx); // Push return address. |
1304 | 1304 |
1305 // Patch the caller to an appropriate specialized stub and return the | 1305 // Patch the caller to an appropriate specialized stub and return the |
1306 // operation result to the caller of the stub. | 1306 // operation result to the caller of the stub. |
1307 __ TailCallExternalReference( | 1307 __ TailCallExternalReference( |
1308 ExternalReference(IC_Utility(IC::kTypeRecordingBinaryOp_Patch)), | 1308 ExternalReference(IC_Utility(IC::kTypeRecordingBinaryOp_Patch), |
| 1309 masm->isolate()), |
1309 5, | 1310 5, |
1310 1); | 1311 1); |
1311 } | 1312 } |
1312 | 1313 |
1313 | 1314 |
1314 // Prepare for a type transition runtime call when the args are already on | 1315 // Prepare for a type transition runtime call when the args are already on |
1315 // the stack, under the return address. | 1316 // the stack, under the return address. |
1316 void TypeRecordingBinaryOpStub::GenerateTypeTransitionWithSavedArgs( | 1317 void TypeRecordingBinaryOpStub::GenerateTypeTransitionWithSavedArgs( |
1317 MacroAssembler* masm) { | 1318 MacroAssembler* masm) { |
1318 __ pop(ecx); // Save return address. | 1319 __ pop(ecx); // Save return address. |
1319 // Left and right arguments are already on top of the stack. | 1320 // Left and right arguments are already on top of the stack. |
1320 // Push this stub's key. Although the operation and the type info are | 1321 // Push this stub's key. Although the operation and the type info are |
1321 // encoded into the key, the encoding is opaque, so push them too. | 1322 // encoded into the key, the encoding is opaque, so push them too. |
1322 __ push(Immediate(Smi::FromInt(MinorKey()))); | 1323 __ push(Immediate(Smi::FromInt(MinorKey()))); |
1323 __ push(Immediate(Smi::FromInt(op_))); | 1324 __ push(Immediate(Smi::FromInt(op_))); |
1324 __ push(Immediate(Smi::FromInt(operands_type_))); | 1325 __ push(Immediate(Smi::FromInt(operands_type_))); |
1325 | 1326 |
1326 __ push(ecx); // Push return address. | 1327 __ push(ecx); // Push return address. |
1327 | 1328 |
1328 // Patch the caller to an appropriate specialized stub and return the | 1329 // Patch the caller to an appropriate specialized stub and return the |
1329 // operation result to the caller of the stub. | 1330 // operation result to the caller of the stub. |
1330 __ TailCallExternalReference( | 1331 __ TailCallExternalReference( |
1331 ExternalReference(IC_Utility(IC::kTypeRecordingBinaryOp_Patch)), | 1332 ExternalReference(IC_Utility(IC::kTypeRecordingBinaryOp_Patch), |
| 1333 masm->isolate()), |
1332 5, | 1334 5, |
1333 1); | 1335 1); |
1334 } | 1336 } |
1335 | 1337 |
1336 | 1338 |
1337 void TypeRecordingBinaryOpStub::Generate(MacroAssembler* masm) { | 1339 void TypeRecordingBinaryOpStub::Generate(MacroAssembler* masm) { |
1338 switch (operands_type_) { | 1340 switch (operands_type_) { |
1339 case TRBinaryOpIC::UNINITIALIZED: | 1341 case TRBinaryOpIC::UNINITIALIZED: |
1340 GenerateTypeTransition(masm); | 1342 GenerateTypeTransition(masm); |
1341 break; | 1343 break; |
(...skipping 297 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1639 } else { | 1641 } else { |
1640 ASSERT(allow_heapnumber_results == ALLOW_HEAPNUMBER_RESULTS); | 1642 ASSERT(allow_heapnumber_results == ALLOW_HEAPNUMBER_RESULTS); |
1641 switch (op_) { | 1643 switch (op_) { |
1642 case Token::SHL: { | 1644 case Token::SHL: { |
1643 Comment perform_float(masm, "-- Perform float operation on smis"); | 1645 Comment perform_float(masm, "-- Perform float operation on smis"); |
1644 __ bind(&use_fp_on_smis); | 1646 __ bind(&use_fp_on_smis); |
1645 // Result we want is in left == edx, so we can put the allocated heap | 1647 // Result we want is in left == edx, so we can put the allocated heap |
1646 // number in eax. | 1648 // number in eax. |
1647 __ AllocateHeapNumber(eax, ecx, ebx, slow); | 1649 __ AllocateHeapNumber(eax, ecx, ebx, slow); |
1648 // Store the result in the HeapNumber and return. | 1650 // Store the result in the HeapNumber and return. |
1649 if (Isolate::Current()->cpu_features()->IsSupported(SSE2)) { | 1651 if (masm->isolate()->cpu_features()->IsSupported(SSE2)) { |
1650 CpuFeatures::Scope use_sse2(SSE2); | 1652 CpuFeatures::Scope use_sse2(SSE2); |
1651 __ cvtsi2sd(xmm0, Operand(left)); | 1653 __ cvtsi2sd(xmm0, Operand(left)); |
1652 __ movdbl(FieldOperand(eax, HeapNumber::kValueOffset), xmm0); | 1654 __ movdbl(FieldOperand(eax, HeapNumber::kValueOffset), xmm0); |
1653 } else { | 1655 } else { |
1654 // It's OK to overwrite the right argument on the stack because we | 1656 // It's OK to overwrite the right argument on the stack because we |
1655 // are about to return. | 1657 // are about to return. |
1656 __ mov(Operand(esp, 1 * kPointerSize), left); | 1658 __ mov(Operand(esp, 1 * kPointerSize), left); |
1657 __ fild_s(Operand(esp, 1 * kPointerSize)); | 1659 __ fild_s(Operand(esp, 1 * kPointerSize)); |
1658 __ fstp_d(FieldOperand(eax, HeapNumber::kValueOffset)); | 1660 __ fstp_d(FieldOperand(eax, HeapNumber::kValueOffset)); |
1659 } | 1661 } |
(...skipping 24 matching lines...) Expand all Loading... |
1684 case Token::DIV: | 1686 case Token::DIV: |
1685 // Left was clobbered but a copy is in edi. Right is in ebx for | 1687 // Left was clobbered but a copy is in edi. Right is in ebx for |
1686 // division. | 1688 // division. |
1687 __ mov(edx, edi); | 1689 __ mov(edx, edi); |
1688 __ mov(eax, right); | 1690 __ mov(eax, right); |
1689 break; | 1691 break; |
1690 default: UNREACHABLE(); | 1692 default: UNREACHABLE(); |
1691 break; | 1693 break; |
1692 } | 1694 } |
1693 __ AllocateHeapNumber(ecx, ebx, no_reg, slow); | 1695 __ AllocateHeapNumber(ecx, ebx, no_reg, slow); |
1694 if (Isolate::Current()->cpu_features()->IsSupported(SSE2)) { | 1696 if (masm->isolate()->cpu_features()->IsSupported(SSE2)) { |
1695 CpuFeatures::Scope use_sse2(SSE2); | 1697 CpuFeatures::Scope use_sse2(SSE2); |
1696 FloatingPointHelper::LoadSSE2Smis(masm, ebx); | 1698 FloatingPointHelper::LoadSSE2Smis(masm, ebx); |
1697 switch (op_) { | 1699 switch (op_) { |
1698 case Token::ADD: __ addsd(xmm0, xmm1); break; | 1700 case Token::ADD: __ addsd(xmm0, xmm1); break; |
1699 case Token::SUB: __ subsd(xmm0, xmm1); break; | 1701 case Token::SUB: __ subsd(xmm0, xmm1); break; |
1700 case Token::MUL: __ mulsd(xmm0, xmm1); break; | 1702 case Token::MUL: __ mulsd(xmm0, xmm1); break; |
1701 case Token::DIV: __ divsd(xmm0, xmm1); break; | 1703 case Token::DIV: __ divsd(xmm0, xmm1); break; |
1702 default: UNREACHABLE(); | 1704 default: UNREACHABLE(); |
1703 } | 1705 } |
1704 __ movdbl(FieldOperand(ecx, HeapNumber::kValueOffset), xmm0); | 1706 __ movdbl(FieldOperand(ecx, HeapNumber::kValueOffset), xmm0); |
(...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1816 ASSERT(operands_type_ == TRBinaryOpIC::INT32); | 1818 ASSERT(operands_type_ == TRBinaryOpIC::INT32); |
1817 | 1819 |
1818 // Floating point case. | 1820 // Floating point case. |
1819 switch (op_) { | 1821 switch (op_) { |
1820 case Token::ADD: | 1822 case Token::ADD: |
1821 case Token::SUB: | 1823 case Token::SUB: |
1822 case Token::MUL: | 1824 case Token::MUL: |
1823 case Token::DIV: { | 1825 case Token::DIV: { |
1824 Label not_floats; | 1826 Label not_floats; |
1825 Label not_int32; | 1827 Label not_int32; |
1826 if (Isolate::Current()->cpu_features()->IsSupported(SSE2)) { | 1828 if (masm->isolate()->cpu_features()->IsSupported(SSE2)) { |
1827 CpuFeatures::Scope use_sse2(SSE2); | 1829 CpuFeatures::Scope use_sse2(SSE2); |
1828 FloatingPointHelper::LoadSSE2Operands(masm, ¬_floats); | 1830 FloatingPointHelper::LoadSSE2Operands(masm, ¬_floats); |
1829 FloatingPointHelper::CheckSSE2OperandsAreInt32(masm, ¬_int32, ecx); | 1831 FloatingPointHelper::CheckSSE2OperandsAreInt32(masm, ¬_int32, ecx); |
1830 switch (op_) { | 1832 switch (op_) { |
1831 case Token::ADD: __ addsd(xmm0, xmm1); break; | 1833 case Token::ADD: __ addsd(xmm0, xmm1); break; |
1832 case Token::SUB: __ subsd(xmm0, xmm1); break; | 1834 case Token::SUB: __ subsd(xmm0, xmm1); break; |
1833 case Token::MUL: __ mulsd(xmm0, xmm1); break; | 1835 case Token::MUL: __ mulsd(xmm0, xmm1); break; |
1834 case Token::DIV: __ divsd(xmm0, xmm1); break; | 1836 case Token::DIV: __ divsd(xmm0, xmm1); break; |
1835 default: UNREACHABLE(); | 1837 default: UNREACHABLE(); |
1836 } | 1838 } |
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1937 __ test(eax, Immediate(kSmiTagMask)); | 1939 __ test(eax, Immediate(kSmiTagMask)); |
1938 __ j(not_zero, &skip_allocation, not_taken); | 1940 __ j(not_zero, &skip_allocation, not_taken); |
1939 // Fall through! | 1941 // Fall through! |
1940 case NO_OVERWRITE: | 1942 case NO_OVERWRITE: |
1941 __ AllocateHeapNumber(eax, ecx, edx, &call_runtime); | 1943 __ AllocateHeapNumber(eax, ecx, edx, &call_runtime); |
1942 __ bind(&skip_allocation); | 1944 __ bind(&skip_allocation); |
1943 break; | 1945 break; |
1944 default: UNREACHABLE(); | 1946 default: UNREACHABLE(); |
1945 } | 1947 } |
1946 // Store the result in the HeapNumber and return. | 1948 // Store the result in the HeapNumber and return. |
1947 if (Isolate::Current()->cpu_features()->IsSupported(SSE2)) { | 1949 if (masm->isolate()->cpu_features()->IsSupported(SSE2)) { |
1948 CpuFeatures::Scope use_sse2(SSE2); | 1950 CpuFeatures::Scope use_sse2(SSE2); |
1949 __ cvtsi2sd(xmm0, Operand(ebx)); | 1951 __ cvtsi2sd(xmm0, Operand(ebx)); |
1950 __ movdbl(FieldOperand(eax, HeapNumber::kValueOffset), xmm0); | 1952 __ movdbl(FieldOperand(eax, HeapNumber::kValueOffset), xmm0); |
1951 } else { | 1953 } else { |
1952 __ mov(Operand(esp, 1 * kPointerSize), ebx); | 1954 __ mov(Operand(esp, 1 * kPointerSize), ebx); |
1953 __ fild_s(Operand(esp, 1 * kPointerSize)); | 1955 __ fild_s(Operand(esp, 1 * kPointerSize)); |
1954 __ fstp_d(FieldOperand(eax, HeapNumber::kValueOffset)); | 1956 __ fstp_d(FieldOperand(eax, HeapNumber::kValueOffset)); |
1955 } | 1957 } |
1956 __ ret(2 * kPointerSize); // Drop two pushed arguments from the stack. | 1958 __ ret(2 * kPointerSize); // Drop two pushed arguments from the stack. |
1957 } | 1959 } |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2017 Label call_runtime; | 2019 Label call_runtime; |
2018 ASSERT(operands_type_ == TRBinaryOpIC::HEAP_NUMBER); | 2020 ASSERT(operands_type_ == TRBinaryOpIC::HEAP_NUMBER); |
2019 | 2021 |
2020 // Floating point case. | 2022 // Floating point case. |
2021 switch (op_) { | 2023 switch (op_) { |
2022 case Token::ADD: | 2024 case Token::ADD: |
2023 case Token::SUB: | 2025 case Token::SUB: |
2024 case Token::MUL: | 2026 case Token::MUL: |
2025 case Token::DIV: { | 2027 case Token::DIV: { |
2026 Label not_floats; | 2028 Label not_floats; |
2027 if (Isolate::Current()->cpu_features()->IsSupported(SSE2)) { | 2029 if (masm->isolate()->cpu_features()->IsSupported(SSE2)) { |
2028 CpuFeatures::Scope use_sse2(SSE2); | 2030 CpuFeatures::Scope use_sse2(SSE2); |
2029 FloatingPointHelper::LoadSSE2Operands(masm, ¬_floats); | 2031 FloatingPointHelper::LoadSSE2Operands(masm, ¬_floats); |
2030 | 2032 |
2031 switch (op_) { | 2033 switch (op_) { |
2032 case Token::ADD: __ addsd(xmm0, xmm1); break; | 2034 case Token::ADD: __ addsd(xmm0, xmm1); break; |
2033 case Token::SUB: __ subsd(xmm0, xmm1); break; | 2035 case Token::SUB: __ subsd(xmm0, xmm1); break; |
2034 case Token::MUL: __ mulsd(xmm0, xmm1); break; | 2036 case Token::MUL: __ mulsd(xmm0, xmm1); break; |
2035 case Token::DIV: __ divsd(xmm0, xmm1); break; | 2037 case Token::DIV: __ divsd(xmm0, xmm1); break; |
2036 default: UNREACHABLE(); | 2038 default: UNREACHABLE(); |
2037 } | 2039 } |
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2120 __ test(eax, Immediate(kSmiTagMask)); | 2122 __ test(eax, Immediate(kSmiTagMask)); |
2121 __ j(not_zero, &skip_allocation, not_taken); | 2123 __ j(not_zero, &skip_allocation, not_taken); |
2122 // Fall through! | 2124 // Fall through! |
2123 case NO_OVERWRITE: | 2125 case NO_OVERWRITE: |
2124 __ AllocateHeapNumber(eax, ecx, edx, &call_runtime); | 2126 __ AllocateHeapNumber(eax, ecx, edx, &call_runtime); |
2125 __ bind(&skip_allocation); | 2127 __ bind(&skip_allocation); |
2126 break; | 2128 break; |
2127 default: UNREACHABLE(); | 2129 default: UNREACHABLE(); |
2128 } | 2130 } |
2129 // Store the result in the HeapNumber and return. | 2131 // Store the result in the HeapNumber and return. |
2130 if (Isolate::Current()->cpu_features()->IsSupported(SSE2)) { | 2132 if (masm->isolate()->cpu_features()->IsSupported(SSE2)) { |
2131 CpuFeatures::Scope use_sse2(SSE2); | 2133 CpuFeatures::Scope use_sse2(SSE2); |
2132 __ cvtsi2sd(xmm0, Operand(ebx)); | 2134 __ cvtsi2sd(xmm0, Operand(ebx)); |
2133 __ movdbl(FieldOperand(eax, HeapNumber::kValueOffset), xmm0); | 2135 __ movdbl(FieldOperand(eax, HeapNumber::kValueOffset), xmm0); |
2134 } else { | 2136 } else { |
2135 __ mov(Operand(esp, 1 * kPointerSize), ebx); | 2137 __ mov(Operand(esp, 1 * kPointerSize), ebx); |
2136 __ fild_s(Operand(esp, 1 * kPointerSize)); | 2138 __ fild_s(Operand(esp, 1 * kPointerSize)); |
2137 __ fstp_d(FieldOperand(eax, HeapNumber::kValueOffset)); | 2139 __ fstp_d(FieldOperand(eax, HeapNumber::kValueOffset)); |
2138 } | 2140 } |
2139 __ ret(2 * kPointerSize); // Drop two pushed arguments from the stack. | 2141 __ ret(2 * kPointerSize); // Drop two pushed arguments from the stack. |
2140 } | 2142 } |
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2221 | 2223 |
2222 GenerateSmiCode(masm, &call_runtime, ALLOW_HEAPNUMBER_RESULTS); | 2224 GenerateSmiCode(masm, &call_runtime, ALLOW_HEAPNUMBER_RESULTS); |
2223 | 2225 |
2224 // Floating point case. | 2226 // Floating point case. |
2225 switch (op_) { | 2227 switch (op_) { |
2226 case Token::ADD: | 2228 case Token::ADD: |
2227 case Token::SUB: | 2229 case Token::SUB: |
2228 case Token::MUL: | 2230 case Token::MUL: |
2229 case Token::DIV: { | 2231 case Token::DIV: { |
2230 Label not_floats; | 2232 Label not_floats; |
2231 if (Isolate::Current()->cpu_features()->IsSupported(SSE2)) { | 2233 if (masm->isolate()->cpu_features()->IsSupported(SSE2)) { |
2232 CpuFeatures::Scope use_sse2(SSE2); | 2234 CpuFeatures::Scope use_sse2(SSE2); |
2233 FloatingPointHelper::LoadSSE2Operands(masm, ¬_floats); | 2235 FloatingPointHelper::LoadSSE2Operands(masm, ¬_floats); |
2234 | 2236 |
2235 switch (op_) { | 2237 switch (op_) { |
2236 case Token::ADD: __ addsd(xmm0, xmm1); break; | 2238 case Token::ADD: __ addsd(xmm0, xmm1); break; |
2237 case Token::SUB: __ subsd(xmm0, xmm1); break; | 2239 case Token::SUB: __ subsd(xmm0, xmm1); break; |
2238 case Token::MUL: __ mulsd(xmm0, xmm1); break; | 2240 case Token::MUL: __ mulsd(xmm0, xmm1); break; |
2239 case Token::DIV: __ divsd(xmm0, xmm1); break; | 2241 case Token::DIV: __ divsd(xmm0, xmm1); break; |
2240 default: UNREACHABLE(); | 2242 default: UNREACHABLE(); |
2241 } | 2243 } |
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2319 __ test(eax, Immediate(kSmiTagMask)); | 2321 __ test(eax, Immediate(kSmiTagMask)); |
2320 __ j(not_zero, &skip_allocation, not_taken); | 2322 __ j(not_zero, &skip_allocation, not_taken); |
2321 // Fall through! | 2323 // Fall through! |
2322 case NO_OVERWRITE: | 2324 case NO_OVERWRITE: |
2323 __ AllocateHeapNumber(eax, ecx, edx, &call_runtime); | 2325 __ AllocateHeapNumber(eax, ecx, edx, &call_runtime); |
2324 __ bind(&skip_allocation); | 2326 __ bind(&skip_allocation); |
2325 break; | 2327 break; |
2326 default: UNREACHABLE(); | 2328 default: UNREACHABLE(); |
2327 } | 2329 } |
2328 // Store the result in the HeapNumber and return. | 2330 // Store the result in the HeapNumber and return. |
2329 if (Isolate::Current()->cpu_features()->IsSupported(SSE2)) { | 2331 if (masm->isolate()->cpu_features()->IsSupported(SSE2)) { |
2330 CpuFeatures::Scope use_sse2(SSE2); | 2332 CpuFeatures::Scope use_sse2(SSE2); |
2331 __ cvtsi2sd(xmm0, Operand(ebx)); | 2333 __ cvtsi2sd(xmm0, Operand(ebx)); |
2332 __ movdbl(FieldOperand(eax, HeapNumber::kValueOffset), xmm0); | 2334 __ movdbl(FieldOperand(eax, HeapNumber::kValueOffset), xmm0); |
2333 } else { | 2335 } else { |
2334 __ mov(Operand(esp, 1 * kPointerSize), ebx); | 2336 __ mov(Operand(esp, 1 * kPointerSize), ebx); |
2335 __ fild_s(Operand(esp, 1 * kPointerSize)); | 2337 __ fild_s(Operand(esp, 1 * kPointerSize)); |
2336 __ fstp_d(FieldOperand(eax, HeapNumber::kValueOffset)); | 2338 __ fstp_d(FieldOperand(eax, HeapNumber::kValueOffset)); |
2337 } | 2339 } |
2338 __ ret(2 * kPointerSize); | 2340 __ ret(2 * kPointerSize); |
2339 } | 2341 } |
(...skipping 177 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2517 __ cmp(Operand(ebx), Immediate(FACTORY->heap_number_map())); | 2519 __ cmp(Operand(ebx), Immediate(FACTORY->heap_number_map())); |
2518 __ j(not_equal, &runtime_call); | 2520 __ j(not_equal, &runtime_call); |
2519 // Input is a HeapNumber. Push it on the FPU stack and load its | 2521 // Input is a HeapNumber. Push it on the FPU stack and load its |
2520 // low and high words into ebx, edx. | 2522 // low and high words into ebx, edx. |
2521 __ fld_d(FieldOperand(eax, HeapNumber::kValueOffset)); | 2523 __ fld_d(FieldOperand(eax, HeapNumber::kValueOffset)); |
2522 __ mov(edx, FieldOperand(eax, HeapNumber::kExponentOffset)); | 2524 __ mov(edx, FieldOperand(eax, HeapNumber::kExponentOffset)); |
2523 __ mov(ebx, FieldOperand(eax, HeapNumber::kMantissaOffset)); | 2525 __ mov(ebx, FieldOperand(eax, HeapNumber::kMantissaOffset)); |
2524 | 2526 |
2525 __ bind(&loaded); | 2527 __ bind(&loaded); |
2526 } else { // UNTAGGED. | 2528 } else { // UNTAGGED. |
2527 if (Isolate::Current()->cpu_features()->IsSupported(SSE4_1)) { | 2529 if (masm->isolate()->cpu_features()->IsSupported(SSE4_1)) { |
2528 CpuFeatures::Scope sse4_scope(SSE4_1); | 2530 CpuFeatures::Scope sse4_scope(SSE4_1); |
2529 __ pextrd(Operand(edx), xmm1, 0x1); // copy xmm1[63..32] to edx. | 2531 __ pextrd(Operand(edx), xmm1, 0x1); // copy xmm1[63..32] to edx. |
2530 } else { | 2532 } else { |
2531 __ pshufd(xmm0, xmm1, 0x1); | 2533 __ pshufd(xmm0, xmm1, 0x1); |
2532 __ movd(Operand(edx), xmm0); | 2534 __ movd(Operand(edx), xmm0); |
2533 } | 2535 } |
2534 __ movd(Operand(ebx), xmm1); | 2536 __ movd(Operand(ebx), xmm1); |
2535 } | 2537 } |
2536 | 2538 |
2537 // ST[0] or xmm1 == double value | 2539 // ST[0] or xmm1 == double value |
(...skipping 10 matching lines...) Expand all Loading... |
2548 __ sar(eax, 8); | 2550 __ sar(eax, 8); |
2549 __ xor_(ecx, Operand(eax)); | 2551 __ xor_(ecx, Operand(eax)); |
2550 ASSERT(IsPowerOf2(TranscendentalCache::SubCache::kCacheSize)); | 2552 ASSERT(IsPowerOf2(TranscendentalCache::SubCache::kCacheSize)); |
2551 __ and_(Operand(ecx), | 2553 __ and_(Operand(ecx), |
2552 Immediate(TranscendentalCache::SubCache::kCacheSize - 1)); | 2554 Immediate(TranscendentalCache::SubCache::kCacheSize - 1)); |
2553 | 2555 |
2554 // ST[0] or xmm1 == double value. | 2556 // ST[0] or xmm1 == double value. |
2555 // ebx = low 32 bits of double value. | 2557 // ebx = low 32 bits of double value. |
2556 // edx = high 32 bits of double value. | 2558 // edx = high 32 bits of double value. |
2557 // ecx = TranscendentalCache::hash(double value). | 2559 // ecx = TranscendentalCache::hash(double value). |
2558 __ mov(eax, | 2560 ExternalReference cache_array = |
2559 Immediate(ExternalReference::transcendental_cache_array_address())); | 2561 ExternalReference::transcendental_cache_array_address(masm->isolate()); |
2560 // Eax points to cache array. | 2562 __ mov(eax, Immediate(cache_array)); |
2561 __ mov(eax, Operand(eax, type_ * sizeof( | 2563 int cache_array_index = |
2562 Isolate::Current()->transcendental_cache()->caches_[0]))); | 2564 type_ * sizeof(masm->isolate()->transcendental_cache()->caches_[0]); |
| 2565 __ mov(eax, Operand(eax, cache_array_index)); |
2563 // Eax points to the cache for the type type_. | 2566 // Eax points to the cache for the type type_. |
2564 // If NULL, the cache hasn't been initialized yet, so go through runtime. | 2567 // If NULL, the cache hasn't been initialized yet, so go through runtime. |
2565 __ test(eax, Operand(eax)); | 2568 __ test(eax, Operand(eax)); |
2566 __ j(zero, &runtime_call_clear_stack); | 2569 __ j(zero, &runtime_call_clear_stack); |
2567 #ifdef DEBUG | 2570 #ifdef DEBUG |
2568 // Check that the layout of cache elements match expectations. | 2571 // Check that the layout of cache elements match expectations. |
2569 { TranscendentalCache::SubCache::Element test_elem[2]; | 2572 { TranscendentalCache::SubCache::Element test_elem[2]; |
2570 char* elem_start = reinterpret_cast<char*>(&test_elem[0]); | 2573 char* elem_start = reinterpret_cast<char*>(&test_elem[0]); |
2571 char* elem2_start = reinterpret_cast<char*>(&test_elem[1]); | 2574 char* elem2_start = reinterpret_cast<char*>(&test_elem[1]); |
2572 char* elem_in0 = reinterpret_cast<char*>(&(test_elem[0].in[0])); | 2575 char* elem_in0 = reinterpret_cast<char*>(&(test_elem[0].in[0])); |
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2638 __ CallRuntimeSaveDoubles(Runtime::kAllocateInNewSpace); | 2641 __ CallRuntimeSaveDoubles(Runtime::kAllocateInNewSpace); |
2639 __ LeaveInternalFrame(); | 2642 __ LeaveInternalFrame(); |
2640 __ Ret(); | 2643 __ Ret(); |
2641 } | 2644 } |
2642 | 2645 |
2643 // Call runtime, doing whatever allocation and cleanup is necessary. | 2646 // Call runtime, doing whatever allocation and cleanup is necessary. |
2644 if (tagged) { | 2647 if (tagged) { |
2645 __ bind(&runtime_call_clear_stack); | 2648 __ bind(&runtime_call_clear_stack); |
2646 __ fstp(0); | 2649 __ fstp(0); |
2647 __ bind(&runtime_call); | 2650 __ bind(&runtime_call); |
2648 __ TailCallExternalReference(ExternalReference(RuntimeFunction()), 1, 1); | 2651 ExternalReference runtime = |
| 2652 ExternalReference(RuntimeFunction(), masm->isolate()); |
| 2653 __ TailCallExternalReference(runtime, 1, 1); |
2649 } else { // UNTAGGED. | 2654 } else { // UNTAGGED. |
2650 __ bind(&runtime_call_clear_stack); | 2655 __ bind(&runtime_call_clear_stack); |
2651 __ bind(&runtime_call); | 2656 __ bind(&runtime_call); |
2652 __ AllocateHeapNumber(eax, edi, no_reg, &skip_cache); | 2657 __ AllocateHeapNumber(eax, edi, no_reg, &skip_cache); |
2653 __ movdbl(FieldOperand(eax, HeapNumber::kValueOffset), xmm1); | 2658 __ movdbl(FieldOperand(eax, HeapNumber::kValueOffset), xmm1); |
2654 __ EnterInternalFrame(); | 2659 __ EnterInternalFrame(); |
2655 __ push(eax); | 2660 __ push(eax); |
2656 __ CallRuntime(RuntimeFunction(), 1); | 2661 __ CallRuntime(RuntimeFunction(), 1); |
2657 __ LeaveInternalFrame(); | 2662 __ LeaveInternalFrame(); |
2658 __ movdbl(xmm1, FieldOperand(eax, HeapNumber::kValueOffset)); | 2663 __ movdbl(xmm1, FieldOperand(eax, HeapNumber::kValueOffset)); |
(...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2769 void IntegerConvert(MacroAssembler* masm, | 2774 void IntegerConvert(MacroAssembler* masm, |
2770 Register source, | 2775 Register source, |
2771 TypeInfo type_info, | 2776 TypeInfo type_info, |
2772 bool use_sse3, | 2777 bool use_sse3, |
2773 Label* conversion_failure) { | 2778 Label* conversion_failure) { |
2774 ASSERT(!source.is(ecx) && !source.is(edi) && !source.is(ebx)); | 2779 ASSERT(!source.is(ecx) && !source.is(edi) && !source.is(ebx)); |
2775 Label done, right_exponent, normal_exponent; | 2780 Label done, right_exponent, normal_exponent; |
2776 Register scratch = ebx; | 2781 Register scratch = ebx; |
2777 Register scratch2 = edi; | 2782 Register scratch2 = edi; |
2778 if (type_info.IsInteger32() && | 2783 if (type_info.IsInteger32() && |
2779 Isolate::Current()->cpu_features()->IsEnabled(SSE2)) { | 2784 masm->isolate()->cpu_features()->IsEnabled(SSE2)) { |
2780 CpuFeatures::Scope scope(SSE2); | 2785 CpuFeatures::Scope scope(SSE2); |
2781 __ cvttsd2si(ecx, FieldOperand(source, HeapNumber::kValueOffset)); | 2786 __ cvttsd2si(ecx, FieldOperand(source, HeapNumber::kValueOffset)); |
2782 return; | 2787 return; |
2783 } | 2788 } |
2784 if (!type_info.IsInteger32() || !use_sse3) { | 2789 if (!type_info.IsInteger32() || !use_sse3) { |
2785 // Get exponent word. | 2790 // Get exponent word. |
2786 __ mov(scratch, FieldOperand(source, HeapNumber::kExponentOffset)); | 2791 __ mov(scratch, FieldOperand(source, HeapNumber::kExponentOffset)); |
2787 // Get exponent alone in scratch2. | 2792 // Get exponent alone in scratch2. |
2788 __ mov(scratch2, scratch); | 2793 __ mov(scratch2, scratch); |
2789 __ and_(scratch2, HeapNumber::kExponentMask); | 2794 __ and_(scratch2, HeapNumber::kExponentMask); |
(...skipping 524 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3314 | 3319 |
3315 // Check if the operand is a heap number. | 3320 // Check if the operand is a heap number. |
3316 __ mov(edx, FieldOperand(eax, HeapObject::kMapOffset)); | 3321 __ mov(edx, FieldOperand(eax, HeapObject::kMapOffset)); |
3317 __ cmp(edx, FACTORY->heap_number_map()); | 3322 __ cmp(edx, FACTORY->heap_number_map()); |
3318 __ j(not_equal, &slow, not_taken); | 3323 __ j(not_equal, &slow, not_taken); |
3319 | 3324 |
3320 // Convert the heap number in eax to an untagged integer in ecx. | 3325 // Convert the heap number in eax to an untagged integer in ecx. |
3321 IntegerConvert(masm, | 3326 IntegerConvert(masm, |
3322 eax, | 3327 eax, |
3323 TypeInfo::Unknown(), | 3328 TypeInfo::Unknown(), |
3324 Isolate::Current()->cpu_features()->IsSupported(SSE3), | 3329 masm->isolate()->cpu_features()->IsSupported(SSE3), |
3325 &slow); | 3330 &slow); |
3326 | 3331 |
3327 // Do the bitwise operation and check if the result fits in a smi. | 3332 // Do the bitwise operation and check if the result fits in a smi. |
3328 NearLabel try_float; | 3333 NearLabel try_float; |
3329 __ not_(ecx); | 3334 __ not_(ecx); |
3330 __ cmp(ecx, 0xc0000000); | 3335 __ cmp(ecx, 0xc0000000); |
3331 __ j(sign, &try_float, not_taken); | 3336 __ j(sign, &try_float, not_taken); |
3332 | 3337 |
3333 // Tag the result as a smi and we're done. | 3338 // Tag the result as a smi and we're done. |
3334 STATIC_ASSERT(kSmiTagSize == 1); | 3339 STATIC_ASSERT(kSmiTagSize == 1); |
3335 __ lea(eax, Operand(ecx, times_2, kSmiTag)); | 3340 __ lea(eax, Operand(ecx, times_2, kSmiTag)); |
3336 __ jmp(&done); | 3341 __ jmp(&done); |
3337 | 3342 |
3338 // Try to store the result in a heap number. | 3343 // Try to store the result in a heap number. |
3339 __ bind(&try_float); | 3344 __ bind(&try_float); |
3340 if (overwrite_ == UNARY_NO_OVERWRITE) { | 3345 if (overwrite_ == UNARY_NO_OVERWRITE) { |
3341 // Allocate a fresh heap number, but don't overwrite eax until | 3346 // Allocate a fresh heap number, but don't overwrite eax until |
3342 // we're sure we can do it without going through the slow case | 3347 // we're sure we can do it without going through the slow case |
3343 // that needs the value in eax. | 3348 // that needs the value in eax. |
3344 __ AllocateHeapNumber(ebx, edx, edi, &slow); | 3349 __ AllocateHeapNumber(ebx, edx, edi, &slow); |
3345 __ mov(eax, Operand(ebx)); | 3350 __ mov(eax, Operand(ebx)); |
3346 } | 3351 } |
3347 if (Isolate::Current()->cpu_features()->IsSupported(SSE2)) { | 3352 if (masm->isolate()->cpu_features()->IsSupported(SSE2)) { |
3348 CpuFeatures::Scope use_sse2(SSE2); | 3353 CpuFeatures::Scope use_sse2(SSE2); |
3349 __ cvtsi2sd(xmm0, Operand(ecx)); | 3354 __ cvtsi2sd(xmm0, Operand(ecx)); |
3350 __ movdbl(FieldOperand(eax, HeapNumber::kValueOffset), xmm0); | 3355 __ movdbl(FieldOperand(eax, HeapNumber::kValueOffset), xmm0); |
3351 } else { | 3356 } else { |
3352 __ push(ecx); | 3357 __ push(ecx); |
3353 __ fild_s(Operand(esp, 0)); | 3358 __ fild_s(Operand(esp, 0)); |
3354 __ pop(ecx); | 3359 __ pop(ecx); |
3355 __ fstp_d(FieldOperand(eax, HeapNumber::kValueOffset)); | 3360 __ fstp_d(FieldOperand(eax, HeapNumber::kValueOffset)); |
3356 } | 3361 } |
3357 } else { | 3362 } else { |
(...skipping 373 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3731 | 3736 |
3732 static const int kLastMatchInfoOffset = 1 * kPointerSize; | 3737 static const int kLastMatchInfoOffset = 1 * kPointerSize; |
3733 static const int kPreviousIndexOffset = 2 * kPointerSize; | 3738 static const int kPreviousIndexOffset = 2 * kPointerSize; |
3734 static const int kSubjectOffset = 3 * kPointerSize; | 3739 static const int kSubjectOffset = 3 * kPointerSize; |
3735 static const int kJSRegExpOffset = 4 * kPointerSize; | 3740 static const int kJSRegExpOffset = 4 * kPointerSize; |
3736 | 3741 |
3737 Label runtime, invoke_regexp; | 3742 Label runtime, invoke_regexp; |
3738 | 3743 |
3739 // Ensure that a RegExp stack is allocated. | 3744 // Ensure that a RegExp stack is allocated. |
3740 ExternalReference address_of_regexp_stack_memory_address = | 3745 ExternalReference address_of_regexp_stack_memory_address = |
3741 ExternalReference::address_of_regexp_stack_memory_address(); | 3746 ExternalReference::address_of_regexp_stack_memory_address( |
| 3747 masm->isolate()); |
3742 ExternalReference address_of_regexp_stack_memory_size = | 3748 ExternalReference address_of_regexp_stack_memory_size = |
3743 ExternalReference::address_of_regexp_stack_memory_size(); | 3749 ExternalReference::address_of_regexp_stack_memory_size(masm->isolate()); |
3744 __ mov(ebx, Operand::StaticVariable(address_of_regexp_stack_memory_size)); | 3750 __ mov(ebx, Operand::StaticVariable(address_of_regexp_stack_memory_size)); |
3745 __ test(ebx, Operand(ebx)); | 3751 __ test(ebx, Operand(ebx)); |
3746 __ j(zero, &runtime, not_taken); | 3752 __ j(zero, &runtime, not_taken); |
3747 | 3753 |
3748 // Check that the first argument is a JSRegExp object. | 3754 // Check that the first argument is a JSRegExp object. |
3749 __ mov(eax, Operand(esp, kJSRegExpOffset)); | 3755 __ mov(eax, Operand(esp, kJSRegExpOffset)); |
3750 STATIC_ASSERT(kSmiTag == 0); | 3756 STATIC_ASSERT(kSmiTag == 0); |
3751 __ test(eax, Immediate(kSmiTagMask)); | 3757 __ test(eax, Immediate(kSmiTagMask)); |
3752 __ j(zero, &runtime); | 3758 __ j(zero, &runtime); |
3753 __ CmpObjectType(eax, JS_REGEXP_TYPE, ecx); | 3759 __ CmpObjectType(eax, JS_REGEXP_TYPE, ecx); |
(...skipping 159 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3913 // Argument 7: Indicate that this is a direct call from JavaScript. | 3919 // Argument 7: Indicate that this is a direct call from JavaScript. |
3914 __ mov(Operand(esp, 6 * kPointerSize), Immediate(1)); | 3920 __ mov(Operand(esp, 6 * kPointerSize), Immediate(1)); |
3915 | 3921 |
3916 // Argument 6: Start (high end) of backtracking stack memory area. | 3922 // Argument 6: Start (high end) of backtracking stack memory area. |
3917 __ mov(ecx, Operand::StaticVariable(address_of_regexp_stack_memory_address)); | 3923 __ mov(ecx, Operand::StaticVariable(address_of_regexp_stack_memory_address)); |
3918 __ add(ecx, Operand::StaticVariable(address_of_regexp_stack_memory_size)); | 3924 __ add(ecx, Operand::StaticVariable(address_of_regexp_stack_memory_size)); |
3919 __ mov(Operand(esp, 5 * kPointerSize), ecx); | 3925 __ mov(Operand(esp, 5 * kPointerSize), ecx); |
3920 | 3926 |
3921 // Argument 5: static offsets vector buffer. | 3927 // Argument 5: static offsets vector buffer. |
3922 __ mov(Operand(esp, 4 * kPointerSize), | 3928 __ mov(Operand(esp, 4 * kPointerSize), |
3923 Immediate(ExternalReference::address_of_static_offsets_vector())); | 3929 Immediate(ExternalReference::address_of_static_offsets_vector( |
| 3930 masm->isolate()))); |
3924 | 3931 |
3925 // Argument 4: End of string data | 3932 // Argument 4: End of string data |
3926 // Argument 3: Start of string data | 3933 // Argument 3: Start of string data |
3927 NearLabel setup_two_byte, setup_rest; | 3934 NearLabel setup_two_byte, setup_rest; |
3928 __ test(edi, Operand(edi)); | 3935 __ test(edi, Operand(edi)); |
3929 __ mov(edi, FieldOperand(eax, String::kLengthOffset)); | 3936 __ mov(edi, FieldOperand(eax, String::kLengthOffset)); |
3930 __ j(zero, &setup_two_byte); | 3937 __ j(zero, &setup_two_byte); |
3931 __ SmiUntag(edi); | 3938 __ SmiUntag(edi); |
3932 __ lea(ecx, FieldOperand(eax, edi, times_1, SeqAsciiString::kHeaderSize)); | 3939 __ lea(ecx, FieldOperand(eax, edi, times_1, SeqAsciiString::kHeaderSize)); |
3933 __ mov(Operand(esp, 3 * kPointerSize), ecx); // Argument 4. | 3940 __ mov(Operand(esp, 3 * kPointerSize), ecx); // Argument 4. |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3965 Label failure; | 3972 Label failure; |
3966 __ cmp(eax, NativeRegExpMacroAssembler::FAILURE); | 3973 __ cmp(eax, NativeRegExpMacroAssembler::FAILURE); |
3967 __ j(equal, &failure, taken); | 3974 __ j(equal, &failure, taken); |
3968 __ cmp(eax, NativeRegExpMacroAssembler::EXCEPTION); | 3975 __ cmp(eax, NativeRegExpMacroAssembler::EXCEPTION); |
3969 // If not exception it can only be retry. Handle that in the runtime system. | 3976 // If not exception it can only be retry. Handle that in the runtime system. |
3970 __ j(not_equal, &runtime); | 3977 __ j(not_equal, &runtime); |
3971 // Result must now be exception. If there is no pending exception already a | 3978 // Result must now be exception. If there is no pending exception already a |
3972 // stack overflow (on the backtrack stack) was detected in RegExp code but | 3979 // stack overflow (on the backtrack stack) was detected in RegExp code but |
3973 // haven't created the exception yet. Handle that in the runtime system. | 3980 // haven't created the exception yet. Handle that in the runtime system. |
3974 // TODO(592): Rerunning the RegExp to get the stack overflow exception. | 3981 // TODO(592): Rerunning the RegExp to get the stack overflow exception. |
3975 ExternalReference pending_exception(Isolate::k_pending_exception_address); | 3982 ExternalReference pending_exception(Isolate::k_pending_exception_address, |
| 3983 masm->isolate()); |
3976 __ mov(edx, | 3984 __ mov(edx, |
3977 Operand::StaticVariable(ExternalReference::the_hole_value_location())); | 3985 Operand::StaticVariable(ExternalReference::the_hole_value_location( |
| 3986 masm->isolate()))); |
3978 __ mov(eax, Operand::StaticVariable(pending_exception)); | 3987 __ mov(eax, Operand::StaticVariable(pending_exception)); |
3979 __ cmp(edx, Operand(eax)); | 3988 __ cmp(edx, Operand(eax)); |
3980 __ j(equal, &runtime); | 3989 __ j(equal, &runtime); |
3981 // For exception, throw the exception again. | 3990 // For exception, throw the exception again. |
3982 | 3991 |
3983 // Clear the pending exception variable. | 3992 // Clear the pending exception variable. |
3984 __ mov(Operand::StaticVariable(pending_exception), edx); | 3993 __ mov(Operand::StaticVariable(pending_exception), edx); |
3985 | 3994 |
3986 // Special handling of termination exceptions which are uncatchable | 3995 // Special handling of termination exceptions which are uncatchable |
3987 // by javascript code. | 3996 // by javascript code. |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4026 __ mov(FieldOperand(ebx, RegExpImpl::kLastSubjectOffset), eax); | 4035 __ mov(FieldOperand(ebx, RegExpImpl::kLastSubjectOffset), eax); |
4027 __ mov(ecx, ebx); | 4036 __ mov(ecx, ebx); |
4028 __ RecordWrite(ecx, RegExpImpl::kLastSubjectOffset, eax, edi); | 4037 __ RecordWrite(ecx, RegExpImpl::kLastSubjectOffset, eax, edi); |
4029 __ mov(eax, Operand(esp, kSubjectOffset)); | 4038 __ mov(eax, Operand(esp, kSubjectOffset)); |
4030 __ mov(FieldOperand(ebx, RegExpImpl::kLastInputOffset), eax); | 4039 __ mov(FieldOperand(ebx, RegExpImpl::kLastInputOffset), eax); |
4031 __ mov(ecx, ebx); | 4040 __ mov(ecx, ebx); |
4032 __ RecordWrite(ecx, RegExpImpl::kLastInputOffset, eax, edi); | 4041 __ RecordWrite(ecx, RegExpImpl::kLastInputOffset, eax, edi); |
4033 | 4042 |
4034 // Get the static offsets vector filled by the native regexp code. | 4043 // Get the static offsets vector filled by the native regexp code. |
4035 ExternalReference address_of_static_offsets_vector = | 4044 ExternalReference address_of_static_offsets_vector = |
4036 ExternalReference::address_of_static_offsets_vector(); | 4045 ExternalReference::address_of_static_offsets_vector(masm->isolate()); |
4037 __ mov(ecx, Immediate(address_of_static_offsets_vector)); | 4046 __ mov(ecx, Immediate(address_of_static_offsets_vector)); |
4038 | 4047 |
4039 // ebx: last_match_info backing store (FixedArray) | 4048 // ebx: last_match_info backing store (FixedArray) |
4040 // ecx: offsets vector | 4049 // ecx: offsets vector |
4041 // edx: number of capture registers | 4050 // edx: number of capture registers |
4042 NearLabel next_capture, done; | 4051 NearLabel next_capture, done; |
4043 // Capture register counter starts from number of capture registers and | 4052 // Capture register counter starts from number of capture registers and |
4044 // counts down until wraping after zero. | 4053 // counts down until wraping after zero. |
4045 __ bind(&next_capture); | 4054 __ bind(&next_capture); |
4046 __ sub(Operand(edx), Immediate(1)); | 4055 __ sub(Operand(edx), Immediate(1)); |
(...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4155 Register scratch1, | 4164 Register scratch1, |
4156 Register scratch2, | 4165 Register scratch2, |
4157 bool object_is_smi, | 4166 bool object_is_smi, |
4158 Label* not_found) { | 4167 Label* not_found) { |
4159 // Use of registers. Register result is used as a temporary. | 4168 // Use of registers. Register result is used as a temporary. |
4160 Register number_string_cache = result; | 4169 Register number_string_cache = result; |
4161 Register mask = scratch1; | 4170 Register mask = scratch1; |
4162 Register scratch = scratch2; | 4171 Register scratch = scratch2; |
4163 | 4172 |
4164 // Load the number string cache. | 4173 // Load the number string cache. |
4165 ExternalReference roots_address = ExternalReference::roots_address(); | 4174 ExternalReference roots_address = |
| 4175 ExternalReference::roots_address(masm->isolate()); |
4166 __ mov(scratch, Immediate(Heap::kNumberStringCacheRootIndex)); | 4176 __ mov(scratch, Immediate(Heap::kNumberStringCacheRootIndex)); |
4167 __ mov(number_string_cache, | 4177 __ mov(number_string_cache, |
4168 Operand::StaticArray(scratch, times_pointer_size, roots_address)); | 4178 Operand::StaticArray(scratch, times_pointer_size, roots_address)); |
4169 // Make the hash mask from the length of the number string cache. It | 4179 // Make the hash mask from the length of the number string cache. It |
4170 // contains two elements (number and string) for each cache entry. | 4180 // contains two elements (number and string) for each cache entry. |
4171 __ mov(mask, FieldOperand(number_string_cache, FixedArray::kLengthOffset)); | 4181 __ mov(mask, FieldOperand(number_string_cache, FixedArray::kLengthOffset)); |
4172 __ shr(mask, kSmiTagSize + 1); // Untag length and divide it by two. | 4182 __ shr(mask, kSmiTagSize + 1); // Untag length and divide it by two. |
4173 __ sub(Operand(mask), Immediate(1)); // Make mask. | 4183 __ sub(Operand(mask), Immediate(1)); // Make mask. |
4174 | 4184 |
4175 // Calculate the entry in the number string cache. The hash value in the | 4185 // Calculate the entry in the number string cache. The hash value in the |
(...skipping 24 matching lines...) Expand all Loading... |
4200 __ and_(scratch, Operand(mask)); | 4210 __ and_(scratch, Operand(mask)); |
4201 Register index = scratch; | 4211 Register index = scratch; |
4202 Register probe = mask; | 4212 Register probe = mask; |
4203 __ mov(probe, | 4213 __ mov(probe, |
4204 FieldOperand(number_string_cache, | 4214 FieldOperand(number_string_cache, |
4205 index, | 4215 index, |
4206 times_twice_pointer_size, | 4216 times_twice_pointer_size, |
4207 FixedArray::kHeaderSize)); | 4217 FixedArray::kHeaderSize)); |
4208 __ test(probe, Immediate(kSmiTagMask)); | 4218 __ test(probe, Immediate(kSmiTagMask)); |
4209 __ j(zero, not_found); | 4219 __ j(zero, not_found); |
4210 if (Isolate::Current()->cpu_features()->IsSupported(SSE2)) { | 4220 if (masm->isolate()->cpu_features()->IsSupported(SSE2)) { |
4211 CpuFeatures::Scope fscope(SSE2); | 4221 CpuFeatures::Scope fscope(SSE2); |
4212 __ movdbl(xmm0, FieldOperand(object, HeapNumber::kValueOffset)); | 4222 __ movdbl(xmm0, FieldOperand(object, HeapNumber::kValueOffset)); |
4213 __ movdbl(xmm1, FieldOperand(probe, HeapNumber::kValueOffset)); | 4223 __ movdbl(xmm1, FieldOperand(probe, HeapNumber::kValueOffset)); |
4214 __ ucomisd(xmm0, xmm1); | 4224 __ ucomisd(xmm0, xmm1); |
4215 } else { | 4225 } else { |
4216 __ fld_d(FieldOperand(object, HeapNumber::kValueOffset)); | 4226 __ fld_d(FieldOperand(object, HeapNumber::kValueOffset)); |
4217 __ fld_d(FieldOperand(probe, HeapNumber::kValueOffset)); | 4227 __ fld_d(FieldOperand(probe, HeapNumber::kValueOffset)); |
4218 __ FCmp(); | 4228 __ FCmp(); |
4219 } | 4229 } |
4220 __ j(parity_even, not_found); // Bail out if NaN is involved. | 4230 __ j(parity_even, not_found); // Bail out if NaN is involved. |
(...skipping 217 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4438 __ j(equal, &return_not_equal); | 4448 __ j(equal, &return_not_equal); |
4439 | 4449 |
4440 // Fall through to the general case. | 4450 // Fall through to the general case. |
4441 __ bind(&slow); | 4451 __ bind(&slow); |
4442 } | 4452 } |
4443 | 4453 |
4444 // Generate the number comparison code. | 4454 // Generate the number comparison code. |
4445 if (include_number_compare_) { | 4455 if (include_number_compare_) { |
4446 Label non_number_comparison; | 4456 Label non_number_comparison; |
4447 Label unordered; | 4457 Label unordered; |
4448 if (Isolate::Current()->cpu_features()->IsSupported(SSE2)) { | 4458 if (masm->isolate()->cpu_features()->IsSupported(SSE2)) { |
4449 CpuFeatures::Scope use_sse2(SSE2); | 4459 CpuFeatures::Scope use_sse2(SSE2); |
4450 CpuFeatures::Scope use_cmov(CMOV); | 4460 CpuFeatures::Scope use_cmov(CMOV); |
4451 | 4461 |
4452 FloatingPointHelper::LoadSSE2Operands(masm, &non_number_comparison); | 4462 FloatingPointHelper::LoadSSE2Operands(masm, &non_number_comparison); |
4453 __ ucomisd(xmm0, xmm1); | 4463 __ ucomisd(xmm0, xmm1); |
4454 | 4464 |
4455 // Don't base result on EFLAGS when a NaN is involved. | 4465 // Don't base result on EFLAGS when a NaN is involved. |
4456 __ j(parity_even, &unordered, not_taken); | 4466 __ j(parity_even, &unordered, not_taken); |
4457 // Return a result of -1, 0, or 1, based on EFLAGS. | 4467 // Return a result of -1, 0, or 1, based on EFLAGS. |
4458 __ mov(eax, 0); // equal | 4468 __ mov(eax, 0); // equal |
(...skipping 198 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4657 __ InvokeFunction(edi, actual, JUMP_FUNCTION); | 4667 __ InvokeFunction(edi, actual, JUMP_FUNCTION); |
4658 | 4668 |
4659 // Slow-case: Non-function called. | 4669 // Slow-case: Non-function called. |
4660 __ bind(&slow); | 4670 __ bind(&slow); |
4661 // CALL_NON_FUNCTION expects the non-function callee as receiver (instead | 4671 // CALL_NON_FUNCTION expects the non-function callee as receiver (instead |
4662 // of the original receiver from the call site). | 4672 // of the original receiver from the call site). |
4663 __ mov(Operand(esp, (argc_ + 1) * kPointerSize), edi); | 4673 __ mov(Operand(esp, (argc_ + 1) * kPointerSize), edi); |
4664 __ Set(eax, Immediate(argc_)); | 4674 __ Set(eax, Immediate(argc_)); |
4665 __ Set(ebx, Immediate(0)); | 4675 __ Set(ebx, Immediate(0)); |
4666 __ GetBuiltinEntry(edx, Builtins::CALL_NON_FUNCTION); | 4676 __ GetBuiltinEntry(edx, Builtins::CALL_NON_FUNCTION); |
4667 Handle<Code> adaptor(Isolate::Current()->builtins()->builtin( | 4677 Handle<Code> adaptor(masm->isolate()->builtins()->builtin( |
4668 Builtins::ArgumentsAdaptorTrampoline)); | 4678 Builtins::ArgumentsAdaptorTrampoline)); |
4669 __ jmp(adaptor, RelocInfo::CODE_TARGET); | 4679 __ jmp(adaptor, RelocInfo::CODE_TARGET); |
4670 } | 4680 } |
4671 | 4681 |
4672 | 4682 |
4673 bool CEntryStub::NeedsImmovableCode() { | 4683 bool CEntryStub::NeedsImmovableCode() { |
4674 return false; | 4684 return false; |
4675 } | 4685 } |
4676 | 4686 |
4677 | 4687 |
(...skipping 26 matching lines...) Expand all Loading... |
4704 // Pass failure code returned from last attempt as first argument to | 4714 // Pass failure code returned from last attempt as first argument to |
4705 // PerformGC. No need to use PrepareCallCFunction/CallCFunction here as the | 4715 // PerformGC. No need to use PrepareCallCFunction/CallCFunction here as the |
4706 // stack alignment is known to be correct. This function takes one argument | 4716 // stack alignment is known to be correct. This function takes one argument |
4707 // which is passed on the stack, and we know that the stack has been | 4717 // which is passed on the stack, and we know that the stack has been |
4708 // prepared to pass at least one argument. | 4718 // prepared to pass at least one argument. |
4709 __ mov(Operand(esp, 0 * kPointerSize), eax); // Result. | 4719 __ mov(Operand(esp, 0 * kPointerSize), eax); // Result. |
4710 __ call(FUNCTION_ADDR(Runtime::PerformGC), RelocInfo::RUNTIME_ENTRY); | 4720 __ call(FUNCTION_ADDR(Runtime::PerformGC), RelocInfo::RUNTIME_ENTRY); |
4711 } | 4721 } |
4712 | 4722 |
4713 ExternalReference scope_depth = | 4723 ExternalReference scope_depth = |
4714 ExternalReference::heap_always_allocate_scope_depth(); | 4724 ExternalReference::heap_always_allocate_scope_depth(masm->isolate()); |
4715 if (always_allocate_scope) { | 4725 if (always_allocate_scope) { |
4716 __ inc(Operand::StaticVariable(scope_depth)); | 4726 __ inc(Operand::StaticVariable(scope_depth)); |
4717 } | 4727 } |
4718 | 4728 |
4719 // Call C function. | 4729 // Call C function. |
4720 __ mov(Operand(esp, 0 * kPointerSize), edi); // argc. | 4730 __ mov(Operand(esp, 0 * kPointerSize), edi); // argc. |
4721 __ mov(Operand(esp, 1 * kPointerSize), esi); // argv. | 4731 __ mov(Operand(esp, 1 * kPointerSize), esi); // argv. |
4722 __ mov(Operand(esp, 2 * kPointerSize), | 4732 __ mov(Operand(esp, 2 * kPointerSize), |
4723 Immediate(ExternalReference::isolate_address())); | 4733 Immediate(ExternalReference::isolate_address())); |
4724 __ call(Operand(ebx)); | 4734 __ call(Operand(ebx)); |
(...skipping 15 matching lines...) Expand all Loading... |
4740 | 4750 |
4741 // Check for failure result. | 4751 // Check for failure result. |
4742 Label failure_returned; | 4752 Label failure_returned; |
4743 STATIC_ASSERT(((kFailureTag + 1) & kFailureTagMask) == 0); | 4753 STATIC_ASSERT(((kFailureTag + 1) & kFailureTagMask) == 0); |
4744 __ lea(ecx, Operand(eax, 1)); | 4754 __ lea(ecx, Operand(eax, 1)); |
4745 // Lower 2 bits of ecx are 0 iff eax has failure tag. | 4755 // Lower 2 bits of ecx are 0 iff eax has failure tag. |
4746 __ test(ecx, Immediate(kFailureTagMask)); | 4756 __ test(ecx, Immediate(kFailureTagMask)); |
4747 __ j(zero, &failure_returned, not_taken); | 4757 __ j(zero, &failure_returned, not_taken); |
4748 | 4758 |
4749 ExternalReference pending_exception_address( | 4759 ExternalReference pending_exception_address( |
4750 Isolate::k_pending_exception_address); | 4760 Isolate::k_pending_exception_address, masm->isolate()); |
4751 | 4761 |
4752 // Check that there is no pending exception, otherwise we | 4762 // Check that there is no pending exception, otherwise we |
4753 // should have returned some failure value. | 4763 // should have returned some failure value. |
4754 if (FLAG_debug_code) { | 4764 if (FLAG_debug_code) { |
4755 __ push(edx); | 4765 __ push(edx); |
4756 __ mov(edx, Operand::StaticVariable( | 4766 __ mov(edx, Operand::StaticVariable( |
4757 ExternalReference::the_hole_value_location())); | 4767 ExternalReference::the_hole_value_location(masm->isolate()))); |
4758 NearLabel okay; | 4768 NearLabel okay; |
4759 __ cmp(edx, Operand::StaticVariable(pending_exception_address)); | 4769 __ cmp(edx, Operand::StaticVariable(pending_exception_address)); |
4760 // Cannot use check here as it attempts to generate call into runtime. | 4770 // Cannot use check here as it attempts to generate call into runtime. |
4761 __ j(equal, &okay); | 4771 __ j(equal, &okay); |
4762 __ int3(); | 4772 __ int3(); |
4763 __ bind(&okay); | 4773 __ bind(&okay); |
4764 __ pop(edx); | 4774 __ pop(edx); |
4765 } | 4775 } |
4766 | 4776 |
4767 // Exit the JavaScript to C++ exit frame. | 4777 // Exit the JavaScript to C++ exit frame. |
4768 __ LeaveExitFrame(save_doubles_); | 4778 __ LeaveExitFrame(save_doubles_); |
4769 __ ret(0); | 4779 __ ret(0); |
4770 | 4780 |
4771 // Handling of failure. | 4781 // Handling of failure. |
4772 __ bind(&failure_returned); | 4782 __ bind(&failure_returned); |
4773 | 4783 |
4774 Label retry; | 4784 Label retry; |
4775 // If the returned exception is RETRY_AFTER_GC continue at retry label | 4785 // If the returned exception is RETRY_AFTER_GC continue at retry label |
4776 STATIC_ASSERT(Failure::RETRY_AFTER_GC == 0); | 4786 STATIC_ASSERT(Failure::RETRY_AFTER_GC == 0); |
4777 __ test(eax, Immediate(((1 << kFailureTypeTagSize) - 1) << kFailureTagSize)); | 4787 __ test(eax, Immediate(((1 << kFailureTypeTagSize) - 1) << kFailureTagSize)); |
4778 __ j(zero, &retry, taken); | 4788 __ j(zero, &retry, taken); |
4779 | 4789 |
4780 // Special handling of out of memory exceptions. | 4790 // Special handling of out of memory exceptions. |
4781 __ cmp(eax, reinterpret_cast<int32_t>(Failure::OutOfMemoryException())); | 4791 __ cmp(eax, reinterpret_cast<int32_t>(Failure::OutOfMemoryException())); |
4782 __ j(equal, throw_out_of_memory_exception); | 4792 __ j(equal, throw_out_of_memory_exception); |
4783 | 4793 |
4784 // Retrieve the pending exception and clear the variable. | 4794 // Retrieve the pending exception and clear the variable. |
| 4795 ExternalReference the_hole_location = |
| 4796 ExternalReference::the_hole_value_location(masm->isolate()); |
4785 __ mov(eax, Operand::StaticVariable(pending_exception_address)); | 4797 __ mov(eax, Operand::StaticVariable(pending_exception_address)); |
4786 __ mov(edx, | 4798 __ mov(edx, Operand::StaticVariable(the_hole_location)); |
4787 Operand::StaticVariable(ExternalReference::the_hole_value_location())); | |
4788 __ mov(Operand::StaticVariable(pending_exception_address), edx); | 4799 __ mov(Operand::StaticVariable(pending_exception_address), edx); |
4789 | 4800 |
4790 // Special handling of termination exceptions which are uncatchable | 4801 // Special handling of termination exceptions which are uncatchable |
4791 // by javascript code. | 4802 // by javascript code. |
4792 __ cmp(eax, FACTORY->termination_exception()); | 4803 __ cmp(eax, FACTORY->termination_exception()); |
4793 __ j(equal, throw_termination_exception); | 4804 __ j(equal, throw_termination_exception); |
4794 | 4805 |
4795 // Handle normal exception. | 4806 // Handle normal exception. |
4796 __ jmp(throw_normal_exception); | 4807 __ jmp(throw_normal_exception); |
4797 | 4808 |
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4882 // Push marker in two places. | 4893 // Push marker in two places. |
4883 int marker = is_construct ? StackFrame::ENTRY_CONSTRUCT : StackFrame::ENTRY; | 4894 int marker = is_construct ? StackFrame::ENTRY_CONSTRUCT : StackFrame::ENTRY; |
4884 __ push(Immediate(Smi::FromInt(marker))); // context slot | 4895 __ push(Immediate(Smi::FromInt(marker))); // context slot |
4885 __ push(Immediate(Smi::FromInt(marker))); // function slot | 4896 __ push(Immediate(Smi::FromInt(marker))); // function slot |
4886 // Save callee-saved registers (C calling conventions). | 4897 // Save callee-saved registers (C calling conventions). |
4887 __ push(edi); | 4898 __ push(edi); |
4888 __ push(esi); | 4899 __ push(esi); |
4889 __ push(ebx); | 4900 __ push(ebx); |
4890 | 4901 |
4891 // Save copies of the top frame descriptor on the stack. | 4902 // Save copies of the top frame descriptor on the stack. |
4892 ExternalReference c_entry_fp(Isolate::k_c_entry_fp_address); | 4903 ExternalReference c_entry_fp(Isolate::k_c_entry_fp_address, masm->isolate()); |
4893 __ push(Operand::StaticVariable(c_entry_fp)); | 4904 __ push(Operand::StaticVariable(c_entry_fp)); |
4894 | 4905 |
4895 #ifdef ENABLE_LOGGING_AND_PROFILING | 4906 #ifdef ENABLE_LOGGING_AND_PROFILING |
4896 // If this is the outermost JS call, set js_entry_sp value. | 4907 // If this is the outermost JS call, set js_entry_sp value. |
4897 ExternalReference js_entry_sp(Isolate::k_js_entry_sp_address); | 4908 ExternalReference js_entry_sp(Isolate::k_js_entry_sp_address, |
| 4909 masm->isolate()); |
4898 __ cmp(Operand::StaticVariable(js_entry_sp), Immediate(0)); | 4910 __ cmp(Operand::StaticVariable(js_entry_sp), Immediate(0)); |
4899 __ j(not_equal, ¬_outermost_js); | 4911 __ j(not_equal, ¬_outermost_js); |
4900 __ mov(Operand::StaticVariable(js_entry_sp), ebp); | 4912 __ mov(Operand::StaticVariable(js_entry_sp), ebp); |
4901 __ bind(¬_outermost_js); | 4913 __ bind(¬_outermost_js); |
4902 #endif | 4914 #endif |
4903 | 4915 |
4904 // Call a faked try-block that does the invoke. | 4916 // Call a faked try-block that does the invoke. |
4905 __ call(&invoke); | 4917 __ call(&invoke); |
4906 | 4918 |
4907 // Caught exception: Store result (exception) in the pending | 4919 // Caught exception: Store result (exception) in the pending |
4908 // exception field in the JSEnv and return a failure sentinel. | 4920 // exception field in the JSEnv and return a failure sentinel. |
4909 ExternalReference pending_exception(Isolate::k_pending_exception_address); | 4921 ExternalReference pending_exception(Isolate::k_pending_exception_address, |
| 4922 masm->isolate()); |
4910 __ mov(Operand::StaticVariable(pending_exception), eax); | 4923 __ mov(Operand::StaticVariable(pending_exception), eax); |
4911 __ mov(eax, reinterpret_cast<int32_t>(Failure::Exception())); | 4924 __ mov(eax, reinterpret_cast<int32_t>(Failure::Exception())); |
4912 __ jmp(&exit); | 4925 __ jmp(&exit); |
4913 | 4926 |
4914 // Invoke: Link this frame into the handler chain. | 4927 // Invoke: Link this frame into the handler chain. |
4915 __ bind(&invoke); | 4928 __ bind(&invoke); |
4916 __ PushTryHandler(IN_JS_ENTRY, JS_ENTRY_HANDLER); | 4929 __ PushTryHandler(IN_JS_ENTRY, JS_ENTRY_HANDLER); |
4917 | 4930 |
4918 // Clear any pending exceptions. | 4931 // Clear any pending exceptions. |
4919 __ mov(edx, | 4932 ExternalReference the_hole_location = |
4920 Operand::StaticVariable(ExternalReference::the_hole_value_location())); | 4933 ExternalReference::the_hole_value_location(masm->isolate()); |
| 4934 __ mov(edx, Operand::StaticVariable(the_hole_location)); |
4921 __ mov(Operand::StaticVariable(pending_exception), edx); | 4935 __ mov(Operand::StaticVariable(pending_exception), edx); |
4922 | 4936 |
4923 // Fake a receiver (NULL). | 4937 // Fake a receiver (NULL). |
4924 __ push(Immediate(0)); // receiver | 4938 __ push(Immediate(0)); // receiver |
4925 | 4939 |
4926 // Invoke the function by calling through JS entry trampoline | 4940 // Invoke the function by calling through JS entry trampoline |
4927 // builtin and pop the faked function when we return. Notice that we | 4941 // builtin and pop the faked function when we return. Notice that we |
4928 // cannot store a reference to the trampoline code directly in this | 4942 // cannot store a reference to the trampoline code directly in this |
4929 // stub, because the builtin stubs may not have been generated yet. | 4943 // stub, because the builtin stubs may not have been generated yet. |
4930 if (is_construct) { | 4944 if (is_construct) { |
4931 ExternalReference construct_entry(Builtins::JSConstructEntryTrampoline); | 4945 ExternalReference construct_entry( |
| 4946 Builtins::JSConstructEntryTrampoline, |
| 4947 masm->isolate()); |
4932 __ mov(edx, Immediate(construct_entry)); | 4948 __ mov(edx, Immediate(construct_entry)); |
4933 } else { | 4949 } else { |
4934 ExternalReference entry(Builtins::JSEntryTrampoline); | 4950 ExternalReference entry(Builtins::JSEntryTrampoline, |
| 4951 masm->isolate()); |
4935 __ mov(edx, Immediate(entry)); | 4952 __ mov(edx, Immediate(entry)); |
4936 } | 4953 } |
4937 __ mov(edx, Operand(edx, 0)); // deref address | 4954 __ mov(edx, Operand(edx, 0)); // deref address |
4938 __ lea(edx, FieldOperand(edx, Code::kHeaderSize)); | 4955 __ lea(edx, FieldOperand(edx, Code::kHeaderSize)); |
4939 __ call(Operand(edx)); | 4956 __ call(Operand(edx)); |
4940 | 4957 |
4941 // Unlink this frame from the handler chain. | 4958 // Unlink this frame from the handler chain. |
4942 __ pop(Operand::StaticVariable(ExternalReference( | 4959 __ pop(Operand::StaticVariable(ExternalReference( |
4943 Isolate::k_handler_address))); | 4960 Isolate::k_handler_address, |
| 4961 masm->isolate()))); |
4944 // Pop next_sp. | 4962 // Pop next_sp. |
4945 __ add(Operand(esp), Immediate(StackHandlerConstants::kSize - kPointerSize)); | 4963 __ add(Operand(esp), Immediate(StackHandlerConstants::kSize - kPointerSize)); |
4946 | 4964 |
4947 #ifdef ENABLE_LOGGING_AND_PROFILING | 4965 #ifdef ENABLE_LOGGING_AND_PROFILING |
4948 // If current EBP value is the same as js_entry_sp value, it means that | 4966 // If current EBP value is the same as js_entry_sp value, it means that |
4949 // the current function is the outermost. | 4967 // the current function is the outermost. |
4950 __ cmp(ebp, Operand::StaticVariable(js_entry_sp)); | 4968 __ cmp(ebp, Operand::StaticVariable(js_entry_sp)); |
4951 __ j(not_equal, ¬_outermost_js_2); | 4969 __ j(not_equal, ¬_outermost_js_2); |
4952 __ mov(Operand::StaticVariable(js_entry_sp), Immediate(0)); | 4970 __ mov(Operand::StaticVariable(js_entry_sp), Immediate(0)); |
4953 __ bind(¬_outermost_js_2); | 4971 __ bind(¬_outermost_js_2); |
4954 #endif | 4972 #endif |
4955 | 4973 |
4956 // Restore the top frame descriptor from the stack. | 4974 // Restore the top frame descriptor from the stack. |
4957 __ bind(&exit); | 4975 __ bind(&exit); |
4958 __ pop(Operand::StaticVariable(ExternalReference( | 4976 __ pop(Operand::StaticVariable(ExternalReference( |
4959 Isolate::k_c_entry_fp_address))); | 4977 Isolate::k_c_entry_fp_address, |
| 4978 masm->isolate()))); |
4960 | 4979 |
4961 // Restore callee-saved registers (C calling conventions). | 4980 // Restore callee-saved registers (C calling conventions). |
4962 __ pop(ebx); | 4981 __ pop(ebx); |
4963 __ pop(esi); | 4982 __ pop(esi); |
4964 __ pop(edi); | 4983 __ pop(edi); |
4965 __ add(Operand(esp), Immediate(2 * kPointerSize)); // remove markers | 4984 __ add(Operand(esp), Immediate(2 * kPointerSize)); // remove markers |
4966 | 4985 |
4967 // Restore frame pointer and return. | 4986 // Restore frame pointer and return. |
4968 __ pop(ebp); | 4987 __ pop(ebp); |
4969 __ ret(0); | 4988 __ ret(0); |
(...skipping 28 matching lines...) Expand all Loading... |
4998 Register scratch = ecx; | 5017 Register scratch = ecx; |
4999 | 5018 |
5000 // Constants describing the call site code to patch. | 5019 // Constants describing the call site code to patch. |
5001 static const int kDeltaToCmpImmediate = 2; | 5020 static const int kDeltaToCmpImmediate = 2; |
5002 static const int kDeltaToMov = 8; | 5021 static const int kDeltaToMov = 8; |
5003 static const int kDeltaToMovImmediate = 9; | 5022 static const int kDeltaToMovImmediate = 9; |
5004 static const int8_t kCmpEdiImmediateByte1 = BitCast<int8_t, uint8_t>(0x81); | 5023 static const int8_t kCmpEdiImmediateByte1 = BitCast<int8_t, uint8_t>(0x81); |
5005 static const int8_t kCmpEdiImmediateByte2 = BitCast<int8_t, uint8_t>(0xff); | 5024 static const int8_t kCmpEdiImmediateByte2 = BitCast<int8_t, uint8_t>(0xff); |
5006 static const int8_t kMovEaxImmediateByte = BitCast<int8_t, uint8_t>(0xb8); | 5025 static const int8_t kMovEaxImmediateByte = BitCast<int8_t, uint8_t>(0xb8); |
5007 | 5026 |
5008 ExternalReference roots_address = ExternalReference::roots_address(); | 5027 ExternalReference roots_address = |
| 5028 ExternalReference::roots_address(masm->isolate()); |
5009 | 5029 |
5010 ASSERT_EQ(object.code(), InstanceofStub::left().code()); | 5030 ASSERT_EQ(object.code(), InstanceofStub::left().code()); |
5011 ASSERT_EQ(function.code(), InstanceofStub::right().code()); | 5031 ASSERT_EQ(function.code(), InstanceofStub::right().code()); |
5012 | 5032 |
5013 // Get the object and function - they are always both needed. | 5033 // Get the object and function - they are always both needed. |
5014 Label slow, not_js_object; | 5034 Label slow, not_js_object; |
5015 if (!HasArgsInRegisters()) { | 5035 if (!HasArgsInRegisters()) { |
5016 __ mov(object, Operand(esp, 2 * kPointerSize)); | 5036 __ mov(object, Operand(esp, 2 * kPointerSize)); |
5017 __ mov(function, Operand(esp, 1 * kPointerSize)); | 5037 __ mov(function, Operand(esp, 1 * kPointerSize)); |
5018 } | 5038 } |
(...skipping 888 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5907 // Collect the two characters in a register. | 5927 // Collect the two characters in a register. |
5908 Register chars = c1; | 5928 Register chars = c1; |
5909 __ shl(c2, kBitsPerByte); | 5929 __ shl(c2, kBitsPerByte); |
5910 __ or_(chars, Operand(c2)); | 5930 __ or_(chars, Operand(c2)); |
5911 | 5931 |
5912 // chars: two character string, char 1 in byte 0 and char 2 in byte 1. | 5932 // chars: two character string, char 1 in byte 0 and char 2 in byte 1. |
5913 // hash: hash of two character string. | 5933 // hash: hash of two character string. |
5914 | 5934 |
5915 // Load the symbol table. | 5935 // Load the symbol table. |
5916 Register symbol_table = c2; | 5936 Register symbol_table = c2; |
5917 ExternalReference roots_address = ExternalReference::roots_address(); | 5937 ExternalReference roots_address = |
| 5938 ExternalReference::roots_address(masm->isolate()); |
5918 __ mov(scratch, Immediate(Heap::kSymbolTableRootIndex)); | 5939 __ mov(scratch, Immediate(Heap::kSymbolTableRootIndex)); |
5919 __ mov(symbol_table, | 5940 __ mov(symbol_table, |
5920 Operand::StaticArray(scratch, times_pointer_size, roots_address)); | 5941 Operand::StaticArray(scratch, times_pointer_size, roots_address)); |
5921 | 5942 |
5922 // Calculate capacity mask from the symbol table capacity. | 5943 // Calculate capacity mask from the symbol table capacity. |
5923 Register mask = scratch2; | 5944 Register mask = scratch2; |
5924 __ mov(mask, FieldOperand(symbol_table, SymbolTable::kCapacityOffset)); | 5945 __ mov(mask, FieldOperand(symbol_table, SymbolTable::kCapacityOffset)); |
5925 __ SmiUntag(mask); | 5946 __ SmiUntag(mask); |
5926 __ sub(Operand(mask), Immediate(1)); | 5947 __ sub(Operand(mask), Immediate(1)); |
5927 | 5948 |
(...skipping 436 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6364 __ test(ecx, Immediate(kSmiTagMask)); | 6385 __ test(ecx, Immediate(kSmiTagMask)); |
6365 __ j(zero, &generic_stub, not_taken); | 6386 __ j(zero, &generic_stub, not_taken); |
6366 | 6387 |
6367 __ CmpObjectType(eax, HEAP_NUMBER_TYPE, ecx); | 6388 __ CmpObjectType(eax, HEAP_NUMBER_TYPE, ecx); |
6368 __ j(not_equal, &miss, not_taken); | 6389 __ j(not_equal, &miss, not_taken); |
6369 __ CmpObjectType(edx, HEAP_NUMBER_TYPE, ecx); | 6390 __ CmpObjectType(edx, HEAP_NUMBER_TYPE, ecx); |
6370 __ j(not_equal, &miss, not_taken); | 6391 __ j(not_equal, &miss, not_taken); |
6371 | 6392 |
6372 // Inlining the double comparison and falling back to the general compare | 6393 // Inlining the double comparison and falling back to the general compare |
6373 // stub if NaN is involved or SS2 or CMOV is unsupported. | 6394 // stub if NaN is involved or SS2 or CMOV is unsupported. |
6374 CpuFeatures* cpu_features = Isolate::Current()->cpu_features(); | 6395 CpuFeatures* cpu_features = masm->isolate()->cpu_features(); |
6375 if (cpu_features->IsSupported(SSE2) && cpu_features->IsSupported(CMOV)) { | 6396 if (cpu_features->IsSupported(SSE2) && cpu_features->IsSupported(CMOV)) { |
6376 CpuFeatures::Scope scope1(SSE2); | 6397 CpuFeatures::Scope scope1(SSE2); |
6377 CpuFeatures::Scope scope2(CMOV); | 6398 CpuFeatures::Scope scope2(CMOV); |
6378 | 6399 |
6379 // Load left and right operand | 6400 // Load left and right operand |
6380 __ movdbl(xmm0, FieldOperand(edx, HeapNumber::kValueOffset)); | 6401 __ movdbl(xmm0, FieldOperand(edx, HeapNumber::kValueOffset)); |
6381 __ movdbl(xmm1, FieldOperand(eax, HeapNumber::kValueOffset)); | 6402 __ movdbl(xmm1, FieldOperand(eax, HeapNumber::kValueOffset)); |
6382 | 6403 |
6383 // Compare operands | 6404 // Compare operands |
6384 __ ucomisd(xmm0, xmm1); | 6405 __ ucomisd(xmm0, xmm1); |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6430 | 6451 |
6431 | 6452 |
6432 void ICCompareStub::GenerateMiss(MacroAssembler* masm) { | 6453 void ICCompareStub::GenerateMiss(MacroAssembler* masm) { |
6433 // Save the registers. | 6454 // Save the registers. |
6434 __ pop(ecx); | 6455 __ pop(ecx); |
6435 __ push(edx); | 6456 __ push(edx); |
6436 __ push(eax); | 6457 __ push(eax); |
6437 __ push(ecx); | 6458 __ push(ecx); |
6438 | 6459 |
6439 // Call the runtime system in a fresh internal frame. | 6460 // Call the runtime system in a fresh internal frame. |
6440 ExternalReference miss = ExternalReference(IC_Utility(IC::kCompareIC_Miss)); | 6461 ExternalReference miss = ExternalReference(IC_Utility(IC::kCompareIC_Miss), |
| 6462 masm->isolate()); |
6441 __ EnterInternalFrame(); | 6463 __ EnterInternalFrame(); |
6442 __ push(edx); | 6464 __ push(edx); |
6443 __ push(eax); | 6465 __ push(eax); |
6444 __ push(Immediate(Smi::FromInt(op_))); | 6466 __ push(Immediate(Smi::FromInt(op_))); |
6445 __ CallExternalReference(miss, 3); | 6467 __ CallExternalReference(miss, 3); |
6446 __ LeaveInternalFrame(); | 6468 __ LeaveInternalFrame(); |
6447 | 6469 |
6448 // Compute the entry point of the rewritten stub. | 6470 // Compute the entry point of the rewritten stub. |
6449 __ lea(edi, FieldOperand(eax, Code::kHeaderSize)); | 6471 __ lea(edi, FieldOperand(eax, Code::kHeaderSize)); |
6450 | 6472 |
6451 // Restore registers. | 6473 // Restore registers. |
6452 __ pop(ecx); | 6474 __ pop(ecx); |
6453 __ pop(eax); | 6475 __ pop(eax); |
6454 __ pop(edx); | 6476 __ pop(edx); |
6455 __ push(ecx); | 6477 __ push(ecx); |
6456 | 6478 |
6457 // Do a tail call to the rewritten stub. | 6479 // Do a tail call to the rewritten stub. |
6458 __ jmp(Operand(edi)); | 6480 __ jmp(Operand(edi)); |
6459 } | 6481 } |
6460 | 6482 |
6461 | 6483 |
6462 #undef __ | 6484 #undef __ |
6463 | 6485 |
6464 } } // namespace v8::internal | 6486 } } // namespace v8::internal |
6465 | 6487 |
6466 #endif // V8_TARGET_ARCH_IA32 | 6488 #endif // V8_TARGET_ARCH_IA32 |
OLD | NEW |