Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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 2117 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2128 __ ldr(r0, MemOperand(sp, 0 * kPointerSize)); | 2128 __ ldr(r0, MemOperand(sp, 0 * kPointerSize)); |
| 2129 | 2129 |
| 2130 // If the argument is a smi, just return. | 2130 // If the argument is a smi, just return. |
| 2131 STATIC_ASSERT(kSmiTag == 0); | 2131 STATIC_ASSERT(kSmiTag == 0); |
| 2132 __ tst(r0, Operand(kSmiTagMask)); | 2132 __ tst(r0, Operand(kSmiTagMask)); |
| 2133 __ Drop(argc + 1, eq); | 2133 __ Drop(argc + 1, eq); |
| 2134 __ Ret(eq); | 2134 __ Ret(eq); |
| 2135 | 2135 |
| 2136 __ CheckMap(r0, r1, Heap::kHeapNumberMapRootIndex, &slow, DONT_DO_SMI_CHECK); | 2136 __ CheckMap(r0, r1, Heap::kHeapNumberMapRootIndex, &slow, DONT_DO_SMI_CHECK); |
| 2137 | 2137 |
| 2138 Label wont_fit_smi, no_vfp_exception, restore_fpscr_and_return; | 2138 Label smi_check, just_return; |
| 2139 | |
| 2140 // If vfp3 is enabled, we use the fpu rounding with the RM (round towards | |
| 2141 // minus infinity) mode. | |
| 2142 | 2139 |
| 2143 // Load the HeapNumber value. | 2140 // Load the HeapNumber value. |
| 2144 // We will need access to the value in the core registers, so we load it | 2141 // We will need access to the value in the core registers, so we load it |
| 2145 // with ldrd and move it to the fpu. It also spares a sub instruction for | 2142 // with ldrd and move it to the fpu. It also spares a sub instruction for |
| 2146 // updating the HeapNumber value address, as vldr expects a multiple | 2143 // updating the HeapNumber value address, as vldr expects a multiple |
| 2147 // of 4 offset. | 2144 // of 4 offset. |
| 2148 __ Ldrd(r4, r5, FieldMemOperand(r0, HeapNumber::kValueOffset)); | 2145 __ Ldrd(r4, r5, FieldMemOperand(r0, HeapNumber::kValueOffset)); |
| 2149 __ vmov(d1, r4, r5); | 2146 __ vmov(d1, r4, r5); |
| 2150 | 2147 |
| 2151 // Backup FPSCR. | 2148 // Check for NaN, Infinities and -0. |
| 2152 __ vmrs(r3); | |
| 2153 // Set custom FPCSR: | |
| 2154 // - Set rounding mode to "Round towards Minus Infinity" | |
| 2155 // (i.e. bits [23:22] = 0b10). | |
| 2156 // - Clear vfp cumulative exception flags (bits [3:0]). | |
| 2157 // - Make sure Flush-to-zero mode control bit is unset (bit 22). | |
| 2158 __ bic(r9, r3, | |
| 2159 Operand(kVFPExceptionMask | kVFPRoundingModeMask | kVFPFlushToZeroMask)); | |
| 2160 __ orr(r9, r9, Operand(kRoundToMinusInf)); | |
| 2161 __ vmsr(r9); | |
| 2162 | |
| 2163 // Convert the argument to an integer. | |
| 2164 __ vcvt_s32_f64(s0, d1, kFPSCRRounding); | |
| 2165 | |
| 2166 // Use vcvt latency to start checking for special cases. | |
| 2167 // Get the argument exponent and clear the sign bit. | |
| 2168 __ bic(r6, r5, Operand(HeapNumber::kSignMask)); | |
| 2169 __ mov(r6, Operand(r6, LSR, HeapNumber::kMantissaBitsInTopWord)); | |
| 2170 | |
| 2171 // Retrieve FPSCR and check for vfp exceptions. | |
| 2172 __ vmrs(r9); | |
| 2173 __ tst(r9, Operand(kVFPExceptionMask)); | |
| 2174 __ b(&no_vfp_exception, eq); | |
| 2175 | |
| 2176 // Check for NaN, Infinity, and -Infinity. | |
| 2177 // They are invariant through a Math.Floor call, so just | 2149 // They are invariant through a Math.Floor call, so just |
| 2178 // return the original argument. | 2150 // return the original argument. |
| 2179 __ sub(r7, r6, Operand(HeapNumber::kExponentMask | 2151 __ Sbfx(r3, r5, HeapNumber::kExponentShift, HeapNumber::kExponentBits); |
| 2180 >> HeapNumber::kMantissaBitsInTopWord), SetCC); | 2152 __ cmp(r3, Operand(-1)); |
| 2181 __ b(&restore_fpscr_and_return, eq); | 2153 __ b(eq, &just_return); |
| 2182 // We had an overflow or underflow in the conversion. Check if we | 2154 __ eor(r3, r5, Operand(0x80000000u)); |
| 2183 // have a big exponent. | 2155 __ orr(r3, r3, r4, SetCC); |
| 2184 __ cmp(r7, Operand(HeapNumber::kMantissaBits)); | 2156 __ b(eq, &just_return); |
| 2185 // If greater or equal, the argument is already round and in r0. | 2157 // Test for values that can be exactly represented as a |
| 2186 __ b(&restore_fpscr_and_return, ge); | 2158 // signed 32-bit integer. |
| 2187 __ b(&wont_fit_smi); | 2159 __ TryDoubleToInt32Exact(r0, d1, d2); |
| 2160 // If exact, check smi | |
| 2161 __ b(eq, &smi_check); | |
| 2162 __ cmp(r5, Operand(0)); | |
| 2188 | 2163 |
| 2189 __ bind(&no_vfp_exception); | 2164 // If input is in ]+0, +inf[, the cmp has clear overflow and negative |
|
hans
2013/03/01 14:47:54
ultra nit: "has cleared"?
| |
| 2190 // Move the result back to general purpose register r0. | 2165 // (V=0 and N=0), the two following instructions won't execute and |
| 2191 __ vmov(r0, s0); | 2166 // we fall through smi_check to check if the result can fit into an smi. |
| 2192 // Check if the result fits into a smi. | 2167 |
| 2168 // If input is in ]-inf, -0[, sub one and, go to slow if we have | |
| 2169 // an overflow. Else we fall through smi check. | |
| 2170 // Hint: if x is a negative, non integer number, | |
| 2171 // floor(x) <=> round_to_zero(x) - 1. | |
| 2172 __ sub(r0, r0, Operand(1), SetCC, mi); | |
| 2173 __ b(vs, &slow); | |
| 2174 | |
| 2175 __ bind(&smi_check); | |
| 2176 // Check if the result can fit into an smi. If we had an overflow, | |
| 2177 // the result is either 0x80000000 or 0x7FFFFFFF and won't fit into an smi. | |
| 2193 __ add(r1, r0, Operand(0x40000000), SetCC); | 2178 __ add(r1, r0, Operand(0x40000000), SetCC); |
| 2194 __ b(&wont_fit_smi, mi); | 2179 // If result doesn't fit into an smi, branch to slow. |
| 2180 __ b(&slow, mi); | |
| 2195 // Tag the result. | 2181 // Tag the result. |
| 2196 STATIC_ASSERT(kSmiTag == 0); | |
| 2197 __ mov(r0, Operand(r0, LSL, kSmiTagSize)); | 2182 __ mov(r0, Operand(r0, LSL, kSmiTagSize)); |
| 2198 | 2183 |
| 2199 // Check for -0. | 2184 __ bind(&just_return); |
| 2200 __ cmp(r0, Operand::Zero()); | |
| 2201 __ b(&restore_fpscr_and_return, ne); | |
| 2202 // r5 already holds the HeapNumber exponent. | |
| 2203 __ tst(r5, Operand(HeapNumber::kSignMask)); | |
| 2204 // If our HeapNumber is negative it was -0, so load its address and return. | |
| 2205 // Else r0 is loaded with 0, so we can also just return. | |
| 2206 __ ldr(r0, MemOperand(sp, 0 * kPointerSize), ne); | |
| 2207 | |
| 2208 __ bind(&restore_fpscr_and_return); | |
| 2209 // Restore FPSCR and return. | |
| 2210 __ vmsr(r3); | |
| 2211 __ Drop(argc + 1); | 2185 __ Drop(argc + 1); |
| 2212 __ Ret(); | 2186 __ Ret(); |
| 2213 | 2187 |
| 2214 __ bind(&wont_fit_smi); | |
| 2215 // Restore FPCSR and fall to slow case. | |
| 2216 __ vmsr(r3); | |
| 2217 | |
| 2218 __ bind(&slow); | 2188 __ bind(&slow); |
| 2219 // Tail call the full function. We do not have to patch the receiver | 2189 // Tail call the full function. We do not have to patch the receiver |
| 2220 // because the function makes no use of it. | 2190 // because the function makes no use of it. |
| 2221 __ InvokeFunction( | 2191 __ InvokeFunction( |
| 2222 function, arguments(), JUMP_FUNCTION, NullCallWrapper(), CALL_AS_METHOD); | 2192 function, arguments(), JUMP_FUNCTION, NullCallWrapper(), CALL_AS_METHOD); |
| 2223 | 2193 |
| 2224 __ bind(&miss); | 2194 __ bind(&miss); |
| 2225 // r2: function name. | 2195 // r2: function name. |
| 2226 GenerateMissBranch(); | 2196 GenerateMissBranch(); |
| 2227 | 2197 |
| (...skipping 1128 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3356 // number and check if the conversion is exact and fits into the smi | 3326 // number and check if the conversion is exact and fits into the smi |
| 3357 // range. | 3327 // range. |
| 3358 __ JumpIfSmi(key, &key_ok); | 3328 __ JumpIfSmi(key, &key_ok); |
| 3359 __ CheckMap(key, | 3329 __ CheckMap(key, |
| 3360 scratch0, | 3330 scratch0, |
| 3361 Heap::kHeapNumberMapRootIndex, | 3331 Heap::kHeapNumberMapRootIndex, |
| 3362 fail, | 3332 fail, |
| 3363 DONT_DO_SMI_CHECK); | 3333 DONT_DO_SMI_CHECK); |
| 3364 __ sub(ip, key, Operand(kHeapObjectTag)); | 3334 __ sub(ip, key, Operand(kHeapObjectTag)); |
| 3365 __ vldr(double_scratch0, ip, HeapNumber::kValueOffset); | 3335 __ vldr(double_scratch0, ip, HeapNumber::kValueOffset); |
| 3366 __ EmitVFPTruncate(kRoundToZero, | 3336 __ TryDoubleToInt32Exact(scratch0, double_scratch0, double_scratch1); |
| 3367 scratch0, | |
| 3368 double_scratch0, | |
| 3369 scratch1, | |
| 3370 double_scratch1, | |
| 3371 kCheckForInexactConversion); | |
| 3372 __ b(ne, fail); | 3337 __ b(ne, fail); |
| 3373 __ TrySmiTag(scratch0, fail, scratch1); | 3338 __ TrySmiTag(scratch0, fail, scratch1); |
| 3374 __ mov(key, scratch0); | 3339 __ mov(key, scratch0); |
| 3375 __ bind(&key_ok); | 3340 __ bind(&key_ok); |
| 3376 } else { | 3341 } else { |
| 3377 // Check that the key is a smi. | 3342 // Check that the key is a smi. |
| 3378 __ JumpIfNotSmi(key, fail); | 3343 __ JumpIfNotSmi(key, fail); |
| 3379 } | 3344 } |
| 3380 } | 3345 } |
| 3381 | 3346 |
| (...skipping 672 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 4054 __ Jump(ic_slow, RelocInfo::CODE_TARGET); | 4019 __ Jump(ic_slow, RelocInfo::CODE_TARGET); |
| 4055 } | 4020 } |
| 4056 } | 4021 } |
| 4057 | 4022 |
| 4058 | 4023 |
| 4059 #undef __ | 4024 #undef __ |
| 4060 | 4025 |
| 4061 } } // namespace v8::internal | 4026 } } // namespace v8::internal |
| 4062 | 4027 |
| 4063 #endif // V8_TARGET_ARCH_ARM | 4028 #endif // V8_TARGET_ARCH_ARM |
| OLD | NEW |