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 1999 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2010 } | 2010 } |
2011 __ SmiNeg(rax, rax, &done); | 2011 __ SmiNeg(rax, rax, &done); |
2012 __ jmp(&slow); // zero, if not handled above, and Smi::kMinValue. | 2012 __ jmp(&slow); // zero, if not handled above, and Smi::kMinValue. |
2013 | 2013 |
2014 // Try floating point case. | 2014 // Try floating point case. |
2015 __ bind(&try_float); | 2015 __ bind(&try_float); |
2016 } else if (FLAG_debug_code) { | 2016 } else if (FLAG_debug_code) { |
2017 __ AbortIfSmi(rax); | 2017 __ AbortIfSmi(rax); |
2018 } | 2018 } |
2019 | 2019 |
2020 __ movq(rdx, FieldOperand(rax, HeapObject::kMapOffset)); | 2020 __ CompareRoot(FieldOperand(rax, HeapObject::kMapOffset), |
2021 __ CompareRoot(rdx, Heap::kHeapNumberMapRootIndex); | 2021 Heap::kHeapNumberMapRootIndex); |
2022 __ j(not_equal, &slow); | 2022 __ j(not_equal, &slow); |
2023 // Operand is a float, negate its value by flipping sign bit. | 2023 // Operand is a float, negate its value by flipping sign bit. |
2024 __ movq(rdx, FieldOperand(rax, HeapNumber::kValueOffset)); | 2024 __ movq(rdx, FieldOperand(rax, HeapNumber::kValueOffset)); |
2025 __ movq(kScratchRegister, Immediate(0x01)); | 2025 __ movq(kScratchRegister, Immediate(0x01)); |
2026 __ shl(kScratchRegister, Immediate(63)); | 2026 __ shl(kScratchRegister, Immediate(63)); |
2027 __ xor_(rdx, kScratchRegister); // Flip sign. | 2027 __ xor_(rdx, kScratchRegister); // Flip sign. |
2028 // rdx is value to store. | 2028 // rdx is value to store. |
2029 if (overwrite_ == UNARY_OVERWRITE) { | 2029 if (overwrite_ == UNARY_OVERWRITE) { |
2030 __ movq(FieldOperand(rax, HeapNumber::kValueOffset), rdx); | 2030 __ movq(FieldOperand(rax, HeapNumber::kValueOffset), rdx); |
2031 } else { | 2031 } else { |
2032 __ AllocateHeapNumber(rcx, rbx, &slow); | 2032 __ AllocateHeapNumber(rcx, rbx, &slow); |
2033 // rcx: allocated 'empty' number | 2033 // rcx: allocated 'empty' number |
2034 __ movq(FieldOperand(rcx, HeapNumber::kValueOffset), rdx); | 2034 __ movq(FieldOperand(rcx, HeapNumber::kValueOffset), rdx); |
2035 __ movq(rax, rcx); | 2035 __ movq(rax, rcx); |
2036 } | 2036 } |
2037 } else if (op_ == Token::BIT_NOT) { | 2037 } else if (op_ == Token::BIT_NOT) { |
2038 if (include_smi_code_) { | 2038 if (include_smi_code_) { |
2039 Label try_float; | 2039 Label try_float; |
2040 __ JumpIfNotSmi(rax, &try_float); | 2040 __ JumpIfNotSmi(rax, &try_float); |
2041 __ SmiNot(rax, rax); | 2041 __ SmiNot(rax, rax); |
2042 __ jmp(&done); | 2042 __ jmp(&done); |
2043 // Try floating point case. | 2043 // Try floating point case. |
2044 __ bind(&try_float); | 2044 __ bind(&try_float); |
2045 } else if (FLAG_debug_code) { | 2045 } else if (FLAG_debug_code) { |
2046 __ AbortIfSmi(rax); | 2046 __ AbortIfSmi(rax); |
2047 } | 2047 } |
2048 | 2048 |
2049 // Check if the operand is a heap number. | 2049 // Check if the operand is a heap number. |
2050 __ movq(rdx, FieldOperand(rax, HeapObject::kMapOffset)); | 2050 __ CompareRoot(FieldOperand(rax, HeapObject::kMapOffset), |
2051 __ CompareRoot(rdx, Heap::kHeapNumberMapRootIndex); | 2051 Heap::kHeapNumberMapRootIndex); |
2052 __ j(not_equal, &slow); | 2052 __ j(not_equal, &slow); |
2053 | 2053 |
2054 // Convert the heap number in rax to an untagged integer in rcx. | 2054 // Convert the heap number in rax to an untagged integer in rcx. |
2055 IntegerConvert(masm, rax, rax); | 2055 IntegerConvert(masm, rax, rax); |
2056 | 2056 |
2057 // Do the bitwise operation and smi tag the result. | 2057 // Do the bitwise operation and smi tag the result. |
2058 __ notl(rax); | 2058 __ notl(rax); |
2059 __ Integer32ToSmi(rax, rax); | 2059 __ Integer32ToSmi(rax, rax); |
2060 } | 2060 } |
2061 | 2061 |
(...skipping 12 matching lines...) Expand all Loading... | |
2074 break; | 2074 break; |
2075 case Token::BIT_NOT: | 2075 case Token::BIT_NOT: |
2076 __ InvokeBuiltin(Builtins::BIT_NOT, JUMP_FUNCTION); | 2076 __ InvokeBuiltin(Builtins::BIT_NOT, JUMP_FUNCTION); |
2077 break; | 2077 break; |
2078 default: | 2078 default: |
2079 UNREACHABLE(); | 2079 UNREACHABLE(); |
2080 } | 2080 } |
2081 } | 2081 } |
2082 | 2082 |
2083 | 2083 |
2084 void MathPowStub::Generate(MacroAssembler* masm) { | |
2085 // Registers are used as follows: | |
2086 // rdx = base | |
2087 // rax = exponent | |
2088 // rcx = temporary, result | |
2089 | |
2090 CpuFeatures::Scope use_sse2(SSE2); | |
Lasse Reichstein
2011/02/28 13:21:41
No need to have SSE2 scopes in X64.
| |
2091 Label allocate_return, call_runtime; | |
2092 | |
2093 // Load input parameters. | |
2094 __ movq(rdx, Operand(rsp, 2 * kPointerSize)); | |
2095 __ movq(rax, Operand(rsp, 1 * kPointerSize)); | |
2096 | |
2097 // Save 1 in xmm3 - we need this several times later on. | |
2098 __ movl(rcx, Immediate(1)); | |
2099 __ cvtlsi2sd(xmm3, rcx); | |
2100 | |
2101 Label exponent_nonsmi; | |
2102 Label base_nonsmi; | |
2103 // If the exponent is a heap number go to that specific case. | |
2104 __ JumpIfNotSmi(rax, &exponent_nonsmi); | |
2105 __ JumpIfNotSmi(rdx, &base_nonsmi); | |
2106 | |
2107 // Optimized version when both exponent and base are smis. | |
2108 Label powi; | |
2109 __ SmiToInteger32(rdx, rdx); | |
2110 __ cvtlsi2sd(xmm0, rdx); | |
2111 __ jmp(&powi); | |
2112 // exponent is smi and base is a heapnumber. | |
2113 __ bind(&base_nonsmi); | |
2114 __ CompareRoot(FieldOperand(rdx, HeapObject::kMapOffset), | |
2115 Heap::kHeapNumberMapRootIndex); | |
2116 __ j(not_equal, &call_runtime); | |
2117 | |
2118 __ movsd(xmm0, FieldOperand(rdx, HeapNumber::kValueOffset)); | |
2119 | |
2120 // Optimized version of pow if exponent is a smi. | |
2121 // xmm0 contains the base. | |
2122 __ bind(&powi); | |
2123 __ SmiToInteger32(rax, rax); | |
2124 | |
2125 // Save exponent in base as we need to check if exponent is negative later. | |
2126 // We know that base and exponent are in different registers. | |
2127 __ movq(rdx, rax); | |
2128 | |
2129 // Get absolute value of exponent. | |
2130 NearLabel no_neg; | |
2131 __ cmpl(rax, Immediate(0)); | |
2132 __ j(greater_equal, &no_neg); | |
2133 __ negl(rax); | |
2134 __ bind(&no_neg); | |
2135 | |
2136 // Load xmm1 with 1. | |
2137 __ movsd(xmm1, xmm3); | |
2138 NearLabel while_true; | |
2139 NearLabel no_multiply; | |
2140 | |
2141 __ bind(&while_true); | |
2142 __ shrl(rax, Immediate(1)); | |
2143 __ j(not_carry, &no_multiply); | |
2144 __ mulsd(xmm1, xmm0); | |
2145 __ bind(&no_multiply); | |
2146 __ mulsd(xmm0, xmm0); | |
2147 __ j(not_zero, &while_true); | |
2148 | |
2149 // base has the original value of the exponent - if the exponent is | |
2150 // negative return 1/result. | |
2151 __ testl(rdx, rdx); | |
2152 __ j(positive, &allocate_return); | |
2153 // Special case if xmm1 has reached infinity. | |
2154 __ movl(rcx, Immediate(0x7FB00000)); | |
Lasse Reichstein
2011/02/28 13:21:41
Could you detect infinity by adding the value to i
William Hesse
2011/02/28 14:36:11
We now divide first, then compare to 0.
On 2011/
| |
2155 __ movd(xmm0, rcx); | |
2156 __ cvtss2sd(xmm0, xmm0); | |
2157 __ ucomisd(xmm0, xmm1); | |
2158 __ j(equal, &call_runtime); | |
2159 __ divsd(xmm3, xmm1); | |
2160 __ movsd(xmm1, xmm3); | |
Lasse Reichstein
2011/02/28 13:21:41
It's worth noticing that if xmm1 is very small, th
William Hesse
2011/02/28 14:36:11
Done.
| |
2161 __ jmp(&allocate_return); | |
2162 | |
2163 // exponent (or both) is a heapnumber - no matter what we should now work | |
Lasse Reichstein
2011/02/28 13:21:41
Capitalize exponent.
| |
2164 // on doubles. | |
2165 __ bind(&exponent_nonsmi); | |
2166 __ CompareRoot(FieldOperand(rax, HeapObject::kMapOffset), | |
2167 Heap::kHeapNumberMapRootIndex); | |
2168 __ j(not_equal, &call_runtime); | |
2169 __ movsd(xmm1, FieldOperand(rax, HeapNumber::kValueOffset)); | |
2170 // Test if exponent is nan. | |
2171 __ ucomisd(xmm1, xmm1); | |
2172 __ j(parity_even, &call_runtime); | |
2173 | |
2174 NearLabel base_not_smi; | |
2175 NearLabel handle_special_cases; | |
2176 __ JumpIfNotSmi(rdx, &base_not_smi); | |
2177 __ SmiToInteger32(rdx, rdx); | |
2178 __ cvtlsi2sd(xmm0, rdx); | |
2179 __ jmp(&handle_special_cases); | |
2180 | |
2181 __ bind(&base_not_smi); | |
2182 __ CompareRoot(FieldOperand(rdx, HeapObject::kMapOffset), | |
2183 Heap::kHeapNumberMapRootIndex); | |
2184 __ j(not_equal, &call_runtime); | |
2185 __ movl(rcx, FieldOperand(rdx, HeapNumber::kExponentOffset)); | |
2186 __ andl(rcx, Immediate(HeapNumber::kExponentMask)); | |
2187 __ cmpl(rcx, Immediate(HeapNumber::kExponentMask)); | |
2188 // base is NaN or +/-Infinity | |
2189 __ j(greater_equal, &call_runtime); | |
Lasse Reichstein
2011/02/28 13:21:41
If the value isn't -Infinity, won't the result be
William Hesse
2011/02/28 14:36:11
The value b^infinity depends on whether b is >, =,
| |
2190 __ movsd(xmm0, FieldOperand(rdx, HeapNumber::kValueOffset)); | |
2191 | |
2192 // base is in xmm0 and exponent is in xmm1. | |
2193 __ bind(&handle_special_cases); | |
2194 NearLabel not_minus_half; | |
2195 // Test for -0.5. | |
2196 // Load xmm2 with -0.5. | |
2197 __ movl(rcx, Immediate(0xBF000000)); | |
Lasse Reichstein
2011/02/28 13:21:41
Is this smaller than loading the exact representat
William Hesse
2011/02/28 14:36:11
Changed.
On 2011/02/28 13:21:41, Lasse Reichstein
| |
2198 __ movd(xmm2, rcx); | |
2199 __ cvtss2sd(xmm2, xmm2); | |
2200 // xmm2 now has -0.5. | |
2201 __ ucomisd(xmm2, xmm1); | |
2202 __ j(not_equal, ¬_minus_half); | |
2203 | |
2204 // Calculates reciprocal of square root. | |
2205 // sqrtsd returns -0 when input is -0. ECMA spec requires +0. | |
2206 __ xorpd(xmm1, xmm1); | |
2207 __ addsd(xmm1, xmm0); | |
2208 __ sqrtsd(xmm1, xmm1); | |
2209 __ divsd(xmm3, xmm1); | |
2210 __ movsd(xmm1, xmm3); | |
2211 __ jmp(&allocate_return); | |
2212 | |
2213 // Test for 0.5. | |
2214 __ bind(¬_minus_half); | |
2215 // Load xmm2 with 0.5. | |
2216 // Since xmm3 is 1 and xmm2 is -0.5 this is simply xmm2 + xmm3. | |
2217 __ addsd(xmm2, xmm3); | |
2218 // xmm2 now has 0.5. | |
2219 __ ucomisd(xmm2, xmm1); | |
2220 __ j(not_equal, &call_runtime); | |
2221 // Calculates square root. | |
2222 // sqrtsd returns -0 when input is -0. ECMA spec requires +0. | |
2223 __ xorpd(xmm1, xmm1); | |
2224 __ addsd(xmm1, xmm0); | |
2225 __ sqrtsd(xmm1, xmm1); | |
2226 | |
2227 __ bind(&allocate_return); | |
2228 __ AllocateHeapNumber(rcx, rax, &call_runtime); | |
2229 __ movsd(FieldOperand(rcx, HeapNumber::kValueOffset), xmm1); | |
2230 __ movq(rax, rcx); | |
2231 __ ret(2 * kPointerSize); | |
2232 | |
2233 __ bind(&call_runtime); | |
2234 __ TailCallRuntime(Runtime::kMath_pow_cfunction, 2, 1); | |
2235 } | |
2236 | |
2237 | |
2084 void ArgumentsAccessStub::GenerateReadElement(MacroAssembler* masm) { | 2238 void ArgumentsAccessStub::GenerateReadElement(MacroAssembler* masm) { |
2085 // The key is in rdx and the parameter count is in rax. | 2239 // The key is in rdx and the parameter count is in rax. |
2086 | 2240 |
2087 // The displacement is used for skipping the frame pointer on the | 2241 // The displacement is used for skipping the frame pointer on the |
2088 // stack. It is the offset of the last parameter (if any) relative | 2242 // stack. It is the offset of the last parameter (if any) relative |
2089 // to the frame pointer. | 2243 // to the frame pointer. |
2090 static const int kDisplacement = 1 * kPointerSize; | 2244 static const int kDisplacement = 1 * kPointerSize; |
2091 | 2245 |
2092 // Check that the key is a smi. | 2246 // Check that the key is a smi. |
2093 Label slow; | 2247 Label slow; |
(...skipping 2841 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
4935 FieldOperand(elements, PixelArray::kExternalPointerOffset)); | 5089 FieldOperand(elements, PixelArray::kExternalPointerOffset)); |
4936 __ movb(Operand(external_pointer, untagged_key, times_1, 0), untagged_value); | 5090 __ movb(Operand(external_pointer, untagged_key, times_1, 0), untagged_value); |
4937 __ ret(0); // Return value in eax. | 5091 __ ret(0); // Return value in eax. |
4938 } | 5092 } |
4939 | 5093 |
4940 #undef __ | 5094 #undef __ |
4941 | 5095 |
4942 } } // namespace v8::internal | 5096 } } // namespace v8::internal |
4943 | 5097 |
4944 #endif // V8_TARGET_ARCH_X64 | 5098 #endif // V8_TARGET_ARCH_X64 |
OLD | NEW |