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 2182 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2193 } | 2193 } |
2194 | 2194 |
2195 | 2195 |
2196 Handle<Code> CallStubCompiler::CompileMathFloorCall( | 2196 Handle<Code> CallStubCompiler::CompileMathFloorCall( |
2197 Handle<Object> object, | 2197 Handle<Object> object, |
2198 Handle<JSObject> holder, | 2198 Handle<JSObject> holder, |
2199 Handle<Cell> cell, | 2199 Handle<Cell> cell, |
2200 Handle<JSFunction> function, | 2200 Handle<JSFunction> function, |
2201 Handle<String> name, | 2201 Handle<String> name, |
2202 Code::StubType type) { | 2202 Code::StubType type) { |
2203 // TODO(872): implement this. | 2203 // ----------- S t a t e ------------- |
2204 return Handle<Code>::null(); | 2204 // -- rcx : name |
| 2205 // -- rsp[0] : return address |
| 2206 // -- rsp[(argc - n) * 4] : arg[n] (zero-based) |
| 2207 // -- ... |
| 2208 // -- rsp[(argc + 1) * 4] : receiver |
| 2209 // ----------------------------------- |
| 2210 |
| 2211 if (!CpuFeatures::IsSupported(SSE2)) { |
| 2212 return Handle<Code>::null(); |
| 2213 } |
| 2214 |
| 2215 CpuFeatureScope use_sse2(masm(), SSE2); |
| 2216 |
| 2217 const int argc = arguments().immediate(); |
| 2218 |
| 2219 // If the object is not a JSObject or we got an unexpected number of |
| 2220 // arguments, bail out to the regular call. |
| 2221 if (!object->IsJSObject() || argc != 1) { |
| 2222 return Handle<Code>::null(); |
| 2223 } |
| 2224 |
| 2225 Label miss; |
| 2226 GenerateNameCheck(name, &miss); |
| 2227 |
| 2228 if (cell.is_null()) { |
| 2229 __ movq(rdx, Operand(rsp, 2 * kPointerSize)); |
| 2230 |
| 2231 STATIC_ASSERT(kSmiTag == 0); |
| 2232 __ JumpIfSmi(rdx, &miss); |
| 2233 |
| 2234 CheckPrototypes(Handle<JSObject>::cast(object), rdx, holder, rbx, rax, rdi, |
| 2235 name, &miss); |
| 2236 } else { |
| 2237 ASSERT(cell->value() == *function); |
| 2238 GenerateGlobalReceiverCheck(Handle<JSObject>::cast(object), holder, name, |
| 2239 &miss); |
| 2240 GenerateLoadFunctionFromCell(cell, function, &miss); |
| 2241 } |
| 2242 |
| 2243 // Load the (only) argument into rax. |
| 2244 __ movq(rax, Operand(rsp, 1 * kPointerSize)); |
| 2245 |
| 2246 // Check if the argument is a smi. |
| 2247 Label smi; |
| 2248 STATIC_ASSERT(kSmiTag == 0); |
| 2249 __ JumpIfSmi(rax, &smi); |
| 2250 |
| 2251 // Check if the argument is a heap number and load its value into xmm0. |
| 2252 Label slow; |
| 2253 __ CheckMap(rax, factory()->heap_number_map(), &slow, DONT_DO_SMI_CHECK); |
| 2254 __ movsd(xmm0, FieldOperand(rax, HeapNumber::kValueOffset)); |
| 2255 |
| 2256 // Check if the argument is strictly positive. Note this also discards NaN. |
| 2257 __ xorpd(xmm1, xmm1); |
| 2258 __ ucomisd(xmm0, xmm1); |
| 2259 __ j(below_equal, &slow); |
| 2260 |
| 2261 // Do a truncating conversion. |
| 2262 __ cvttsd2si(rax, xmm0); |
| 2263 |
| 2264 // Checks for 0x80000000 which signals a failed conversion. |
| 2265 Label conversion_failure; |
| 2266 __ cmpl(rax, Immediate(0x80000000)); |
| 2267 __ j(equal, &conversion_failure); |
| 2268 |
| 2269 // Smi tag and return. |
| 2270 __ Integer32ToSmi(rax, rax); |
| 2271 __ bind(&smi); |
| 2272 __ ret(2 * kPointerSize); |
| 2273 |
| 2274 // Check if the argument is < 2^kMantissaBits. |
| 2275 Label already_round; |
| 2276 __ bind(&conversion_failure); |
| 2277 int64_t kTwoMantissaBits= V8_INT64_C(0x4330000000000000); |
| 2278 __ movq(rbx, kTwoMantissaBits, RelocInfo::NONE64); |
| 2279 __ movq(xmm1, rbx); |
| 2280 __ ucomisd(xmm0, xmm1); |
| 2281 __ j(above_equal, &already_round); |
| 2282 |
| 2283 // Save a copy of the argument. |
| 2284 __ movaps(xmm2, xmm0); |
| 2285 |
| 2286 // Compute (argument + 2^kMantissaBits) - 2^kMantissaBits. |
| 2287 __ addsd(xmm0, xmm1); |
| 2288 __ subsd(xmm0, xmm1); |
| 2289 |
| 2290 // Compare the argument and the tentative result to get the right mask: |
| 2291 // if xmm2 < xmm0: |
| 2292 // xmm2 = 1...1 |
| 2293 // else: |
| 2294 // xmm2 = 0...0 |
| 2295 __ cmpltsd(xmm2, xmm0); |
| 2296 |
| 2297 // Subtract 1 if the argument was less than the tentative result. |
| 2298 int64_t kOne = V8_INT64_C(0x3ff0000000000000); |
| 2299 __ movq(rbx, kOne, RelocInfo::NONE64); |
| 2300 __ movq(xmm1, rbx); |
| 2301 __ andpd(xmm1, xmm2); |
| 2302 __ subsd(xmm0, xmm1); |
| 2303 |
| 2304 // Return a new heap number. |
| 2305 __ AllocateHeapNumber(rax, rbx, &slow); |
| 2306 __ movsd(FieldOperand(rax, HeapNumber::kValueOffset), xmm0); |
| 2307 __ ret(2 * kPointerSize); |
| 2308 |
| 2309 // Return the argument (when it's an already round heap number). |
| 2310 __ bind(&already_round); |
| 2311 __ movq(rax, Operand(rsp, 1 * kPointerSize)); |
| 2312 __ ret(2 * kPointerSize); |
| 2313 |
| 2314 // Tail call the full function. We do not have to patch the receiver |
| 2315 // because the function makes no use of it. |
| 2316 __ bind(&slow); |
| 2317 ParameterCount expected(function); |
| 2318 __ InvokeFunction(function, expected, arguments(), |
| 2319 JUMP_FUNCTION, NullCallWrapper(), CALL_AS_METHOD); |
| 2320 |
| 2321 __ bind(&miss); |
| 2322 // rcx: function name. |
| 2323 GenerateMissBranch(); |
| 2324 |
| 2325 // Return the generated code. |
| 2326 return GetCode(type, name); |
2205 } | 2327 } |
2206 | 2328 |
2207 | 2329 |
2208 Handle<Code> CallStubCompiler::CompileMathAbsCall( | 2330 Handle<Code> CallStubCompiler::CompileMathAbsCall( |
2209 Handle<Object> object, | 2331 Handle<Object> object, |
2210 Handle<JSObject> holder, | 2332 Handle<JSObject> holder, |
2211 Handle<Cell> cell, | 2333 Handle<Cell> cell, |
2212 Handle<JSFunction> function, | 2334 Handle<JSFunction> function, |
2213 Handle<String> name, | 2335 Handle<String> name, |
2214 Code::StubType type) { | 2336 Code::StubType type) { |
(...skipping 820 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3035 // ----------------------------------- | 3157 // ----------------------------------- |
3036 TailCallBuiltin(masm, Builtins::kKeyedLoadIC_MissForceGeneric); | 3158 TailCallBuiltin(masm, Builtins::kKeyedLoadIC_MissForceGeneric); |
3037 } | 3159 } |
3038 | 3160 |
3039 | 3161 |
3040 #undef __ | 3162 #undef __ |
3041 | 3163 |
3042 } } // namespace v8::internal | 3164 } } // namespace v8::internal |
3043 | 3165 |
3044 #endif // V8_TARGET_ARCH_X64 | 3166 #endif // V8_TARGET_ARCH_X64 |
OLD | NEW |