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

Side by Side Diff: src/ia32/code-stubs-ia32.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/full-codegen/full-codegen.cc ('k') | src/interpreter/interpreter-intrinsics.h » ('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 2012 the V8 project authors. All rights reserved. 1 // Copyright 2012 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_IA32 5 #if V8_TARGET_ARCH_IA32
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/base/bits.h" 9 #include "src/base/bits.h"
10 #include "src/bootstrapper.h" 10 #include "src/bootstrapper.h"
(...skipping 308 matching lines...) Expand 10 before | Expand all | Expand 10 after
319 __ mov(scratch, FieldOperand(eax, HeapObject::kMapOffset)); 319 __ mov(scratch, FieldOperand(eax, HeapObject::kMapOffset));
320 __ cmp(scratch, factory->heap_number_map()); 320 __ cmp(scratch, factory->heap_number_map());
321 __ j(not_equal, non_float); // argument in eax is not a number -> NaN 321 __ j(not_equal, non_float); // argument in eax is not a number -> NaN
322 322
323 // Fall-through: Both operands are numbers. 323 // Fall-through: Both operands are numbers.
324 __ bind(&done); 324 __ bind(&done);
325 } 325 }
326 326
327 327
328 void MathPowStub::Generate(MacroAssembler* masm) { 328 void MathPowStub::Generate(MacroAssembler* masm) {
329 Factory* factory = isolate()->factory();
330 const Register exponent = MathPowTaggedDescriptor::exponent(); 329 const Register exponent = MathPowTaggedDescriptor::exponent();
331 DCHECK(exponent.is(eax)); 330 DCHECK(exponent.is(eax));
332 const Register base = edx;
333 const Register scratch = ecx; 331 const Register scratch = ecx;
334 const XMMRegister double_result = xmm3; 332 const XMMRegister double_result = xmm3;
335 const XMMRegister double_base = xmm2; 333 const XMMRegister double_base = xmm2;
336 const XMMRegister double_exponent = xmm1; 334 const XMMRegister double_exponent = xmm1;
337 const XMMRegister double_scratch = xmm4; 335 const XMMRegister double_scratch = xmm4;
338 336
339 Label call_runtime, done, exponent_not_smi, int_exponent; 337 Label call_runtime, done, exponent_not_smi, int_exponent;
340 338
341 // Save 1 in double_result - we need this several times later on. 339 // Save 1 in double_result - we need this several times later on.
342 __ mov(scratch, Immediate(1)); 340 __ mov(scratch, Immediate(1));
343 __ Cvtsi2sd(double_result, scratch); 341 __ Cvtsi2sd(double_result, scratch);
344 342
345 if (exponent_type() == ON_STACK) { 343 if (exponent_type() == TAGGED) {
346 Label base_is_smi, unpack_exponent;
347 // The exponent and base are supplied as arguments on the stack.
348 // This can only happen if the stub is called from non-optimized code.
349 // Load input parameters from stack.
350 __ mov(base, Operand(esp, 2 * kPointerSize));
351 __ mov(exponent, Operand(esp, 1 * kPointerSize));
352
353 __ JumpIfSmi(base, &base_is_smi, Label::kNear);
354 __ cmp(FieldOperand(base, HeapObject::kMapOffset),
355 factory->heap_number_map());
356 __ j(not_equal, &call_runtime);
357
358 __ movsd(double_base, FieldOperand(base, HeapNumber::kValueOffset));
359 __ jmp(&unpack_exponent, Label::kNear);
360
361 __ bind(&base_is_smi);
362 __ SmiUntag(base);
363 __ Cvtsi2sd(double_base, base);
364
365 __ bind(&unpack_exponent);
366 __ JumpIfNotSmi(exponent, &exponent_not_smi, Label::kNear); 344 __ JumpIfNotSmi(exponent, &exponent_not_smi, Label::kNear);
367 __ SmiUntag(exponent); 345 __ SmiUntag(exponent);
368 __ jmp(&int_exponent); 346 __ jmp(&int_exponent);
369
370 __ bind(&exponent_not_smi);
371 __ cmp(FieldOperand(exponent, HeapObject::kMapOffset),
372 factory->heap_number_map());
373 __ j(not_equal, &call_runtime);
374 __ movsd(double_exponent,
375 FieldOperand(exponent, HeapNumber::kValueOffset));
376 } else if (exponent_type() == TAGGED) {
377 __ JumpIfNotSmi(exponent, &exponent_not_smi, Label::kNear);
378 __ SmiUntag(exponent);
379 __ jmp(&int_exponent);
380 347
381 __ bind(&exponent_not_smi); 348 __ bind(&exponent_not_smi);
382 __ movsd(double_exponent, 349 __ movsd(double_exponent,
383 FieldOperand(exponent, HeapNumber::kValueOffset)); 350 FieldOperand(exponent, HeapNumber::kValueOffset));
384 } 351 }
385 352
386 if (exponent_type() != INTEGER) { 353 if (exponent_type() != INTEGER) {
387 Label fast_power, try_arithmetic_simplification; 354 Label fast_power, try_arithmetic_simplification;
388 __ DoubleToI(exponent, double_exponent, double_scratch, 355 __ DoubleToI(exponent, double_exponent, double_scratch,
389 TREAT_MINUS_ZERO_AS_ZERO, &try_arithmetic_simplification, 356 TREAT_MINUS_ZERO_AS_ZERO, &try_arithmetic_simplification,
390 &try_arithmetic_simplification, 357 &try_arithmetic_simplification,
391 &try_arithmetic_simplification); 358 &try_arithmetic_simplification);
392 __ jmp(&int_exponent); 359 __ jmp(&int_exponent);
393 360
394 __ bind(&try_arithmetic_simplification); 361 __ bind(&try_arithmetic_simplification);
395 // Skip to runtime if possibly NaN (indicated by the indefinite integer). 362 // Skip to runtime if possibly NaN (indicated by the indefinite integer).
396 __ cvttsd2si(exponent, Operand(double_exponent)); 363 __ cvttsd2si(exponent, Operand(double_exponent));
397 __ cmp(exponent, Immediate(0x1)); 364 __ cmp(exponent, Immediate(0x1));
398 __ j(overflow, &call_runtime); 365 __ j(overflow, &call_runtime);
399 366
400 if (exponent_type() == ON_STACK) {
401 // Detect square root case. Crankshaft detects constant +/-0.5 at
402 // compile time and uses DoMathPowHalf instead. We then skip this check
403 // for non-constant cases of +/-0.5 as these hardly occur.
404 Label continue_sqrt, continue_rsqrt, not_plus_half;
405 // Test for 0.5.
406 // Load double_scratch with 0.5.
407 __ mov(scratch, Immediate(0x3F000000u));
408 __ movd(double_scratch, scratch);
409 __ cvtss2sd(double_scratch, double_scratch);
410 // Already ruled out NaNs for exponent.
411 __ ucomisd(double_scratch, double_exponent);
412 __ j(not_equal, &not_plus_half, Label::kNear);
413
414 // Calculates square root of base. Check for the special case of
415 // Math.pow(-Infinity, 0.5) == Infinity (ECMA spec, 15.8.2.13).
416 // According to IEEE-754, single-precision -Infinity has the highest
417 // 9 bits set and the lowest 23 bits cleared.
418 __ mov(scratch, 0xFF800000u);
419 __ movd(double_scratch, scratch);
420 __ cvtss2sd(double_scratch, double_scratch);
421 __ ucomisd(double_base, double_scratch);
422 // Comparing -Infinity with NaN results in "unordered", which sets the
423 // zero flag as if both were equal. However, it also sets the carry flag.
424 __ j(not_equal, &continue_sqrt, Label::kNear);
425 __ j(carry, &continue_sqrt, Label::kNear);
426
427 // Set result to Infinity in the special case.
428 __ xorps(double_result, double_result);
429 __ subsd(double_result, double_scratch);
430 __ jmp(&done);
431
432 __ bind(&continue_sqrt);
433 // sqrtsd returns -0 when input is -0. ECMA spec requires +0.
434 __ xorps(double_scratch, double_scratch);
435 __ addsd(double_scratch, double_base); // Convert -0 to +0.
436 __ sqrtsd(double_result, double_scratch);
437 __ jmp(&done);
438
439 // Test for -0.5.
440 __ bind(&not_plus_half);
441 // Load double_exponent with -0.5 by substracting 1.
442 __ subsd(double_scratch, double_result);
443 // Already ruled out NaNs for exponent.
444 __ ucomisd(double_scratch, double_exponent);
445 __ j(not_equal, &fast_power, Label::kNear);
446
447 // Calculates reciprocal of square root of base. Check for the special
448 // case of Math.pow(-Infinity, -0.5) == 0 (ECMA spec, 15.8.2.13).
449 // According to IEEE-754, single-precision -Infinity has the highest
450 // 9 bits set and the lowest 23 bits cleared.
451 __ mov(scratch, 0xFF800000u);
452 __ movd(double_scratch, scratch);
453 __ cvtss2sd(double_scratch, double_scratch);
454 __ ucomisd(double_base, double_scratch);
455 // Comparing -Infinity with NaN results in "unordered", which sets the
456 // zero flag as if both were equal. However, it also sets the carry flag.
457 __ j(not_equal, &continue_rsqrt, Label::kNear);
458 __ j(carry, &continue_rsqrt, Label::kNear);
459
460 // Set result to 0 in the special case.
461 __ xorps(double_result, double_result);
462 __ jmp(&done);
463
464 __ bind(&continue_rsqrt);
465 // sqrtsd returns -0 when input is -0. ECMA spec requires +0.
466 __ xorps(double_exponent, double_exponent);
467 __ addsd(double_exponent, double_base); // Convert -0 to +0.
468 __ sqrtsd(double_exponent, double_exponent);
469 __ divsd(double_result, double_exponent);
470 __ jmp(&done);
471 }
472
473 // Using FPU instructions to calculate power. 367 // Using FPU instructions to calculate power.
474 Label fast_power_failed; 368 Label fast_power_failed;
475 __ bind(&fast_power); 369 __ bind(&fast_power);
476 __ fnclex(); // Clear flags to catch exceptions later. 370 __ fnclex(); // Clear flags to catch exceptions later.
477 // Transfer (B)ase and (E)xponent onto the FPU register stack. 371 // Transfer (B)ase and (E)xponent onto the FPU register stack.
478 __ sub(esp, Immediate(kDoubleSize)); 372 __ sub(esp, Immediate(kDoubleSize));
479 __ movsd(Operand(esp, 0), double_exponent); 373 __ movsd(Operand(esp, 0), double_exponent);
480 __ fld_d(Operand(esp, 0)); // E 374 __ fld_d(Operand(esp, 0)); // E
481 __ movsd(Operand(esp, 0), double_base); 375 __ movsd(Operand(esp, 0), double_base);
482 __ fld_d(Operand(esp, 0)); // B, E 376 __ fld_d(Operand(esp, 0)); // B, E
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after
552 // Due to subnormals, x^-y == (1/x)^y does not hold in all cases. 446 // Due to subnormals, x^-y == (1/x)^y does not hold in all cases.
553 __ xorps(double_scratch2, double_scratch2); 447 __ xorps(double_scratch2, double_scratch2);
554 __ ucomisd(double_scratch2, double_result); // Result cannot be NaN. 448 __ ucomisd(double_scratch2, double_result); // Result cannot be NaN.
555 // double_exponent aliased as double_scratch2 has already been overwritten 449 // double_exponent aliased as double_scratch2 has already been overwritten
556 // and may not have contained the exponent value in the first place when the 450 // and may not have contained the exponent value in the first place when the
557 // exponent is a smi. We reset it with exponent value before bailing out. 451 // exponent is a smi. We reset it with exponent value before bailing out.
558 __ j(not_equal, &done); 452 __ j(not_equal, &done);
559 __ Cvtsi2sd(double_exponent, exponent); 453 __ Cvtsi2sd(double_exponent, exponent);
560 454
561 // Returning or bailing out. 455 // Returning or bailing out.
562 if (exponent_type() == ON_STACK) { 456 __ bind(&call_runtime);
563 // The arguments are still on the stack. 457 {
564 __ bind(&call_runtime); 458 AllowExternalCallThatCantCauseGC scope(masm);
565 __ TailCallRuntime(Runtime::kMathPowRT); 459 __ PrepareCallCFunction(4, scratch);
460 __ movsd(Operand(esp, 0 * kDoubleSize), double_base);
461 __ movsd(Operand(esp, 1 * kDoubleSize), double_exponent);
462 __ CallCFunction(ExternalReference::power_double_double_function(isolate()),
463 4);
464 }
465 // Return value is in st(0) on ia32.
466 // Store it into the (fixed) result register.
467 __ sub(esp, Immediate(kDoubleSize));
468 __ fstp_d(Operand(esp, 0));
469 __ movsd(double_result, Operand(esp, 0));
470 __ add(esp, Immediate(kDoubleSize));
566 471
567 // The stub is called from non-optimized code, which expects the result 472 __ bind(&done);
568 // as heap number in exponent. 473 __ ret(0);
569 __ bind(&done);
570 __ AllocateHeapNumber(eax, scratch, base, &call_runtime);
571 __ movsd(FieldOperand(eax, HeapNumber::kValueOffset), double_result);
572 __ ret(2 * kPointerSize);
573 } else {
574 __ bind(&call_runtime);
575 {
576 AllowExternalCallThatCantCauseGC scope(masm);
577 __ PrepareCallCFunction(4, scratch);
578 __ movsd(Operand(esp, 0 * kDoubleSize), double_base);
579 __ movsd(Operand(esp, 1 * kDoubleSize), double_exponent);
580 __ CallCFunction(
581 ExternalReference::power_double_double_function(isolate()), 4);
582 }
583 // Return value is in st(0) on ia32.
584 // Store it into the (fixed) result register.
585 __ sub(esp, Immediate(kDoubleSize));
586 __ fstp_d(Operand(esp, 0));
587 __ movsd(double_result, Operand(esp, 0));
588 __ add(esp, Immediate(kDoubleSize));
589
590 __ bind(&done);
591 __ ret(0);
592 }
593 } 474 }
594 475
595
596 void FunctionPrototypeStub::Generate(MacroAssembler* masm) { 476 void FunctionPrototypeStub::Generate(MacroAssembler* masm) {
597 Label miss; 477 Label miss;
598 Register receiver = LoadDescriptor::ReceiverRegister(); 478 Register receiver = LoadDescriptor::ReceiverRegister();
599 // With careful management, we won't have to save slot and vector on 479 // With careful management, we won't have to save slot and vector on
600 // the stack. Simply handle the possibly missing case first. 480 // the stack. Simply handle the possibly missing case first.
601 // TODO(mvstanton): this code can be more efficient. 481 // TODO(mvstanton): this code can be more efficient.
602 __ cmp(FieldOperand(receiver, JSFunction::kPrototypeOrInitialMapOffset), 482 __ cmp(FieldOperand(receiver, JSFunction::kPrototypeOrInitialMapOffset),
603 Immediate(isolate()->factory()->the_hole_value())); 483 Immediate(isolate()->factory()->the_hole_value()));
604 __ j(equal, &miss); 484 __ j(equal, &miss);
605 __ TryGetFunctionPrototype(receiver, eax, ebx, &miss); 485 __ TryGetFunctionPrototype(receiver, eax, ebx, &miss);
(...skipping 5012 matching lines...) Expand 10 before | Expand all | Expand 10 after
5618 kStackUnwindSpace, nullptr, return_value_operand, 5498 kStackUnwindSpace, nullptr, return_value_operand,
5619 NULL); 5499 NULL);
5620 } 5500 }
5621 5501
5622 #undef __ 5502 #undef __
5623 5503
5624 } // namespace internal 5504 } // namespace internal
5625 } // namespace v8 5505 } // namespace v8
5626 5506
5627 #endif // V8_TARGET_ARCH_IA32 5507 #endif // V8_TARGET_ARCH_IA32
OLDNEW
« no previous file with comments | « src/full-codegen/full-codegen.cc ('k') | src/interpreter/interpreter-intrinsics.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698