Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(55)

Side by Side Diff: src/x64/code-stubs-x64.cc

Issue 2103733003: [turbofan] Introduce Float64Pow and NumberPow operators. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: REBASE on ARM64 bug fix. Created 4 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/runtime/runtime-maths.cc ('k') | test/cctest/compiler/test-code-assembler.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2013 the V8 project authors. All rights reserved. 1 // Copyright 2013 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #if V8_TARGET_ARCH_X64 5 #if V8_TARGET_ARCH_X64
6 6
7 #include "src/code-stubs.h" 7 #include "src/code-stubs.h"
8 #include "src/api-arguments.h" 8 #include "src/api-arguments.h"
9 #include "src/bootstrapper.h" 9 #include "src/bootstrapper.h"
10 #include "src/codegen.h" 10 #include "src/codegen.h"
(...skipping 196 matching lines...) Expand 10 before | Expand all | Expand 10 after
207 __ bind(&load_smi_rax); 207 __ bind(&load_smi_rax);
208 __ SmiToInteger32(kScratchRegister, rax); 208 __ SmiToInteger32(kScratchRegister, rax);
209 __ Cvtlsi2sd(xmm1, kScratchRegister); 209 __ Cvtlsi2sd(xmm1, kScratchRegister);
210 __ bind(&done); 210 __ bind(&done);
211 } 211 }
212 212
213 213
214 void MathPowStub::Generate(MacroAssembler* masm) { 214 void MathPowStub::Generate(MacroAssembler* masm) {
215 const Register exponent = MathPowTaggedDescriptor::exponent(); 215 const Register exponent = MathPowTaggedDescriptor::exponent();
216 DCHECK(exponent.is(rdx)); 216 DCHECK(exponent.is(rdx));
217 const Register base = rax;
218 const Register scratch = rcx; 217 const Register scratch = rcx;
219 const XMMRegister double_result = xmm3; 218 const XMMRegister double_result = xmm3;
220 const XMMRegister double_base = xmm2; 219 const XMMRegister double_base = xmm2;
221 const XMMRegister double_exponent = xmm1; 220 const XMMRegister double_exponent = xmm1;
222 const XMMRegister double_scratch = xmm4; 221 const XMMRegister double_scratch = xmm4;
223 222
224 Label call_runtime, done, exponent_not_smi, int_exponent; 223 Label call_runtime, done, exponent_not_smi, int_exponent;
225 224
226 // Save 1 in double_result - we need this several times later on. 225 // Save 1 in double_result - we need this several times later on.
227 __ movp(scratch, Immediate(1)); 226 __ movp(scratch, Immediate(1));
228 __ Cvtlsi2sd(double_result, scratch); 227 __ Cvtlsi2sd(double_result, scratch);
229 228
230 if (exponent_type() == ON_STACK) { 229 if (exponent_type() == TAGGED) {
231 Label base_is_smi, unpack_exponent;
232 // The exponent and base are supplied as arguments on the stack.
233 // This can only happen if the stub is called from non-optimized code.
234 // Load input parameters from stack.
235 StackArgumentsAccessor args(rsp, 2, ARGUMENTS_DONT_CONTAIN_RECEIVER);
236 __ movp(base, args.GetArgumentOperand(0));
237 __ movp(exponent, args.GetArgumentOperand(1));
238 __ JumpIfSmi(base, &base_is_smi, Label::kNear);
239 __ CompareRoot(FieldOperand(base, HeapObject::kMapOffset),
240 Heap::kHeapNumberMapRootIndex);
241 __ j(not_equal, &call_runtime);
242
243 __ Movsd(double_base, FieldOperand(base, HeapNumber::kValueOffset));
244 __ jmp(&unpack_exponent, Label::kNear);
245
246 __ bind(&base_is_smi);
247 __ SmiToInteger32(base, base);
248 __ Cvtlsi2sd(double_base, base);
249 __ bind(&unpack_exponent);
250
251 __ JumpIfNotSmi(exponent, &exponent_not_smi, Label::kNear); 230 __ JumpIfNotSmi(exponent, &exponent_not_smi, Label::kNear);
252 __ SmiToInteger32(exponent, exponent); 231 __ SmiToInteger32(exponent, exponent);
253 __ jmp(&int_exponent); 232 __ jmp(&int_exponent);
254
255 __ bind(&exponent_not_smi);
256 __ CompareRoot(FieldOperand(exponent, HeapObject::kMapOffset),
257 Heap::kHeapNumberMapRootIndex);
258 __ j(not_equal, &call_runtime);
259 __ Movsd(double_exponent, FieldOperand(exponent, HeapNumber::kValueOffset));
260 } else if (exponent_type() == TAGGED) {
261 __ JumpIfNotSmi(exponent, &exponent_not_smi, Label::kNear);
262 __ SmiToInteger32(exponent, exponent);
263 __ jmp(&int_exponent);
264 233
265 __ bind(&exponent_not_smi); 234 __ bind(&exponent_not_smi);
266 __ Movsd(double_exponent, FieldOperand(exponent, HeapNumber::kValueOffset)); 235 __ Movsd(double_exponent, FieldOperand(exponent, HeapNumber::kValueOffset));
267 } 236 }
268 237
269 if (exponent_type() != INTEGER) { 238 if (exponent_type() != INTEGER) {
270 Label fast_power, try_arithmetic_simplification; 239 Label fast_power, try_arithmetic_simplification;
271 // Detect integer exponents stored as double. 240 // Detect integer exponents stored as double.
272 __ DoubleToI(exponent, double_exponent, double_scratch, 241 __ DoubleToI(exponent, double_exponent, double_scratch,
273 TREAT_MINUS_ZERO_AS_ZERO, &try_arithmetic_simplification, 242 TREAT_MINUS_ZERO_AS_ZERO, &try_arithmetic_simplification,
274 &try_arithmetic_simplification, 243 &try_arithmetic_simplification,
275 &try_arithmetic_simplification); 244 &try_arithmetic_simplification);
276 __ jmp(&int_exponent); 245 __ jmp(&int_exponent);
277 246
278 __ bind(&try_arithmetic_simplification); 247 __ bind(&try_arithmetic_simplification);
279 __ Cvttsd2si(exponent, double_exponent); 248 __ Cvttsd2si(exponent, double_exponent);
280 // Skip to runtime if possibly NaN (indicated by the indefinite integer). 249 // Skip to runtime if possibly NaN (indicated by the indefinite integer).
281 __ cmpl(exponent, Immediate(0x1)); 250 __ cmpl(exponent, Immediate(0x1));
282 __ j(overflow, &call_runtime); 251 __ j(overflow, &call_runtime);
283 252
284 if (exponent_type() == ON_STACK) {
285 // Detect square root case. Crankshaft detects constant +/-0.5 at
286 // compile time and uses DoMathPowHalf instead. We then skip this check
287 // for non-constant cases of +/-0.5 as these hardly occur.
288 Label continue_sqrt, continue_rsqrt, not_plus_half;
289 // Test for 0.5.
290 // Load double_scratch with 0.5.
291 __ movq(scratch, V8_UINT64_C(0x3FE0000000000000));
292 __ Movq(double_scratch, scratch);
293 // Already ruled out NaNs for exponent.
294 __ Ucomisd(double_scratch, double_exponent);
295 __ j(not_equal, &not_plus_half, Label::kNear);
296
297 // Calculates square root of base. Check for the special case of
298 // Math.pow(-Infinity, 0.5) == Infinity (ECMA spec, 15.8.2.13).
299 // According to IEEE-754, double-precision -Infinity has the highest
300 // 12 bits set and the lowest 52 bits cleared.
301 __ movq(scratch, V8_UINT64_C(0xFFF0000000000000));
302 __ Movq(double_scratch, scratch);
303 __ Ucomisd(double_scratch, double_base);
304 // Comparing -Infinity with NaN results in "unordered", which sets the
305 // zero flag as if both were equal. However, it also sets the carry flag.
306 __ j(not_equal, &continue_sqrt, Label::kNear);
307 __ j(carry, &continue_sqrt, Label::kNear);
308
309 // Set result to Infinity in the special case.
310 __ Xorpd(double_result, double_result);
311 __ Subsd(double_result, double_scratch);
312 __ jmp(&done);
313
314 __ bind(&continue_sqrt);
315 // sqrtsd returns -0 when input is -0. ECMA spec requires +0.
316 __ Xorpd(double_scratch, double_scratch);
317 __ Addsd(double_scratch, double_base); // Convert -0 to 0.
318 __ Sqrtsd(double_result, double_scratch);
319 __ jmp(&done);
320
321 // Test for -0.5.
322 __ bind(&not_plus_half);
323 // Load double_scratch with -0.5 by substracting 1.
324 __ Subsd(double_scratch, double_result);
325 // Already ruled out NaNs for exponent.
326 __ Ucomisd(double_scratch, double_exponent);
327 __ j(not_equal, &fast_power, Label::kNear);
328
329 // Calculates reciprocal of square root of base. Check for the special
330 // case of Math.pow(-Infinity, -0.5) == 0 (ECMA spec, 15.8.2.13).
331 // According to IEEE-754, double-precision -Infinity has the highest
332 // 12 bits set and the lowest 52 bits cleared.
333 __ movq(scratch, V8_UINT64_C(0xFFF0000000000000));
334 __ Movq(double_scratch, scratch);
335 __ Ucomisd(double_scratch, double_base);
336 // Comparing -Infinity with NaN results in "unordered", which sets the
337 // zero flag as if both were equal. However, it also sets the carry flag.
338 __ j(not_equal, &continue_rsqrt, Label::kNear);
339 __ j(carry, &continue_rsqrt, Label::kNear);
340
341 // Set result to 0 in the special case.
342 __ Xorpd(double_result, double_result);
343 __ jmp(&done);
344
345 __ bind(&continue_rsqrt);
346 // sqrtsd returns -0 when input is -0. ECMA spec requires +0.
347 __ Xorpd(double_exponent, double_exponent);
348 __ Addsd(double_exponent, double_base); // Convert -0 to +0.
349 __ Sqrtsd(double_exponent, double_exponent);
350 __ Divsd(double_result, double_exponent);
351 __ jmp(&done);
352 }
353
354 // Using FPU instructions to calculate power. 253 // Using FPU instructions to calculate power.
355 Label fast_power_failed; 254 Label fast_power_failed;
356 __ bind(&fast_power); 255 __ bind(&fast_power);
357 __ fnclex(); // Clear flags to catch exceptions later. 256 __ fnclex(); // Clear flags to catch exceptions later.
358 // Transfer (B)ase and (E)xponent onto the FPU register stack. 257 // Transfer (B)ase and (E)xponent onto the FPU register stack.
359 __ subp(rsp, Immediate(kDoubleSize)); 258 __ subp(rsp, Immediate(kDoubleSize));
360 __ Movsd(Operand(rsp, 0), double_exponent); 259 __ Movsd(Operand(rsp, 0), double_exponent);
361 __ fld_d(Operand(rsp, 0)); // E 260 __ fld_d(Operand(rsp, 0)); // E
362 __ Movsd(Operand(rsp, 0), double_base); 261 __ Movsd(Operand(rsp, 0), double_base);
363 __ fld_d(Operand(rsp, 0)); // B, E 262 __ fld_d(Operand(rsp, 0)); // B, E
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after
432 // Due to subnormals, x^-y == (1/x)^y does not hold in all cases. 331 // Due to subnormals, x^-y == (1/x)^y does not hold in all cases.
433 __ Xorpd(double_scratch2, double_scratch2); 332 __ Xorpd(double_scratch2, double_scratch2);
434 __ Ucomisd(double_scratch2, double_result); 333 __ Ucomisd(double_scratch2, double_result);
435 // double_exponent aliased as double_scratch2 has already been overwritten 334 // double_exponent aliased as double_scratch2 has already been overwritten
436 // and may not have contained the exponent value in the first place when the 335 // and may not have contained the exponent value in the first place when the
437 // input was a smi. We reset it with exponent value before bailing out. 336 // input was a smi. We reset it with exponent value before bailing out.
438 __ j(not_equal, &done); 337 __ j(not_equal, &done);
439 __ Cvtlsi2sd(double_exponent, exponent); 338 __ Cvtlsi2sd(double_exponent, exponent);
440 339
441 // Returning or bailing out. 340 // Returning or bailing out.
442 if (exponent_type() == ON_STACK) { 341 __ bind(&call_runtime);
443 // The arguments are still on the stack. 342 // Move base to the correct argument register. Exponent is already in xmm1.
444 __ bind(&call_runtime); 343 __ Movsd(xmm0, double_base);
445 __ TailCallRuntime(Runtime::kMathPowRT); 344 DCHECK(double_exponent.is(xmm1));
345 {
346 AllowExternalCallThatCantCauseGC scope(masm);
347 __ PrepareCallCFunction(2);
348 __ CallCFunction(ExternalReference::power_double_double_function(isolate()),
349 2);
350 }
351 // Return value is in xmm0.
352 __ Movsd(double_result, xmm0);
446 353
447 // The stub is called from non-optimized code, which expects the result 354 __ bind(&done);
448 // as heap number in rax. 355 __ ret(0);
449 __ bind(&done);
450 __ AllocateHeapNumber(rax, rcx, &call_runtime);
451 __ Movsd(FieldOperand(rax, HeapNumber::kValueOffset), double_result);
452 __ ret(2 * kPointerSize);
453 } else {
454 __ bind(&call_runtime);
455 // Move base to the correct argument register. Exponent is already in xmm1.
456 __ Movsd(xmm0, double_base);
457 DCHECK(double_exponent.is(xmm1));
458 {
459 AllowExternalCallThatCantCauseGC scope(masm);
460 __ PrepareCallCFunction(2);
461 __ CallCFunction(
462 ExternalReference::power_double_double_function(isolate()), 2);
463 }
464 // Return value is in xmm0.
465 __ Movsd(double_result, xmm0);
466
467 __ bind(&done);
468 __ ret(0);
469 }
470 } 356 }
471 357
472 358
473 void FunctionPrototypeStub::Generate(MacroAssembler* masm) { 359 void FunctionPrototypeStub::Generate(MacroAssembler* masm) {
474 Label miss; 360 Label miss;
475 Register receiver = LoadDescriptor::ReceiverRegister(); 361 Register receiver = LoadDescriptor::ReceiverRegister();
476 // Ensure that the vector and slot registers won't be clobbered before 362 // Ensure that the vector and slot registers won't be clobbered before
477 // calling the miss handler. 363 // calling the miss handler.
478 DCHECK(!AreAliased(r8, r9, LoadWithVectorDescriptor::VectorRegister(), 364 DCHECK(!AreAliased(r8, r9, LoadWithVectorDescriptor::VectorRegister(),
479 LoadDescriptor::SlotRegister())); 365 LoadDescriptor::SlotRegister()));
(...skipping 4850 matching lines...) Expand 10 before | Expand all | Expand 10 after
5330 kStackUnwindSpace, nullptr, return_value_operand, 5216 kStackUnwindSpace, nullptr, return_value_operand,
5331 NULL); 5217 NULL);
5332 } 5218 }
5333 5219
5334 #undef __ 5220 #undef __
5335 5221
5336 } // namespace internal 5222 } // namespace internal
5337 } // namespace v8 5223 } // namespace v8
5338 5224
5339 #endif // V8_TARGET_ARCH_X64 5225 #endif // V8_TARGET_ARCH_X64
OLDNEW
« no previous file with comments | « src/runtime/runtime-maths.cc ('k') | test/cctest/compiler/test-code-assembler.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698