| OLD | NEW |
| 1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 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 3350 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3361 void LCodeGen::DoCallConstantFunction(LCallConstantFunction* instr) { | 3361 void LCodeGen::DoCallConstantFunction(LCallConstantFunction* instr) { |
| 3362 ASSERT(ToRegister(instr->result()).is(rax)); | 3362 ASSERT(ToRegister(instr->result()).is(rax)); |
| 3363 CallKnownFunction(instr->function(), | 3363 CallKnownFunction(instr->function(), |
| 3364 instr->arity(), | 3364 instr->arity(), |
| 3365 instr, | 3365 instr, |
| 3366 CALL_AS_METHOD, | 3366 CALL_AS_METHOD, |
| 3367 RDI_UNINITIALIZED); | 3367 RDI_UNINITIALIZED); |
| 3368 } | 3368 } |
| 3369 | 3369 |
| 3370 | 3370 |
| 3371 void LCodeGen::DoDeferredMathAbsTaggedHeapNumber(LUnaryMathOperation* instr) { | 3371 void LCodeGen::DoDeferredMathAbsTaggedHeapNumber(LMathAbs* instr) { |
| 3372 Register input_reg = ToRegister(instr->value()); | 3372 Register input_reg = ToRegister(instr->value()); |
| 3373 __ CompareRoot(FieldOperand(input_reg, HeapObject::kMapOffset), | 3373 __ CompareRoot(FieldOperand(input_reg, HeapObject::kMapOffset), |
| 3374 Heap::kHeapNumberMapRootIndex); | 3374 Heap::kHeapNumberMapRootIndex); |
| 3375 DeoptimizeIf(not_equal, instr->environment()); | 3375 DeoptimizeIf(not_equal, instr->environment()); |
| 3376 | 3376 |
| 3377 Label done; | 3377 Label done; |
| 3378 Register tmp = input_reg.is(rax) ? rcx : rax; | 3378 Register tmp = input_reg.is(rax) ? rcx : rax; |
| 3379 Register tmp2 = tmp.is(rcx) ? rdx : input_reg.is(rcx) ? rdx : rcx; | 3379 Register tmp2 = tmp.is(rcx) ? rdx : input_reg.is(rcx) ? rdx : rcx; |
| 3380 | 3380 |
| 3381 // Preserve the value of all registers. | 3381 // Preserve the value of all registers. |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3413 __ movq(tmp2, FieldOperand(input_reg, HeapNumber::kValueOffset)); | 3413 __ movq(tmp2, FieldOperand(input_reg, HeapNumber::kValueOffset)); |
| 3414 __ shl(tmp2, Immediate(1)); | 3414 __ shl(tmp2, Immediate(1)); |
| 3415 __ shr(tmp2, Immediate(1)); | 3415 __ shr(tmp2, Immediate(1)); |
| 3416 __ movq(FieldOperand(tmp, HeapNumber::kValueOffset), tmp2); | 3416 __ movq(FieldOperand(tmp, HeapNumber::kValueOffset), tmp2); |
| 3417 __ StoreToSafepointRegisterSlot(input_reg, tmp); | 3417 __ StoreToSafepointRegisterSlot(input_reg, tmp); |
| 3418 | 3418 |
| 3419 __ bind(&done); | 3419 __ bind(&done); |
| 3420 } | 3420 } |
| 3421 | 3421 |
| 3422 | 3422 |
| 3423 void LCodeGen::EmitIntegerMathAbs(LUnaryMathOperation* instr) { | 3423 void LCodeGen::EmitIntegerMathAbs(LMathAbs* instr) { |
| 3424 Register input_reg = ToRegister(instr->value()); | 3424 Register input_reg = ToRegister(instr->value()); |
| 3425 __ testl(input_reg, input_reg); | 3425 __ testl(input_reg, input_reg); |
| 3426 Label is_positive; | 3426 Label is_positive; |
| 3427 __ j(not_sign, &is_positive); | 3427 __ j(not_sign, &is_positive); |
| 3428 __ negl(input_reg); // Sets flags. | 3428 __ negl(input_reg); // Sets flags. |
| 3429 DeoptimizeIf(negative, instr->environment()); | 3429 DeoptimizeIf(negative, instr->environment()); |
| 3430 __ bind(&is_positive); | 3430 __ bind(&is_positive); |
| 3431 } | 3431 } |
| 3432 | 3432 |
| 3433 | 3433 |
| 3434 void LCodeGen::DoMathAbs(LUnaryMathOperation* instr) { | 3434 void LCodeGen::DoMathAbs(LMathAbs* instr) { |
| 3435 // Class for deferred case. | 3435 // Class for deferred case. |
| 3436 class DeferredMathAbsTaggedHeapNumber: public LDeferredCode { | 3436 class DeferredMathAbsTaggedHeapNumber: public LDeferredCode { |
| 3437 public: | 3437 public: |
| 3438 DeferredMathAbsTaggedHeapNumber(LCodeGen* codegen, | 3438 DeferredMathAbsTaggedHeapNumber(LCodeGen* codegen, LMathAbs* instr) |
| 3439 LUnaryMathOperation* instr) | |
| 3440 : LDeferredCode(codegen), instr_(instr) { } | 3439 : LDeferredCode(codegen), instr_(instr) { } |
| 3441 virtual void Generate() { | 3440 virtual void Generate() { |
| 3442 codegen()->DoDeferredMathAbsTaggedHeapNumber(instr_); | 3441 codegen()->DoDeferredMathAbsTaggedHeapNumber(instr_); |
| 3443 } | 3442 } |
| 3444 virtual LInstruction* instr() { return instr_; } | 3443 virtual LInstruction* instr() { return instr_; } |
| 3445 private: | 3444 private: |
| 3446 LUnaryMathOperation* instr_; | 3445 LMathAbs* instr_; |
| 3447 }; | 3446 }; |
| 3448 | 3447 |
| 3449 ASSERT(instr->value()->Equals(instr->result())); | 3448 ASSERT(instr->value()->Equals(instr->result())); |
| 3450 Representation r = instr->hydrogen()->value()->representation(); | 3449 Representation r = instr->hydrogen()->value()->representation(); |
| 3451 | 3450 |
| 3452 if (r.IsDouble()) { | 3451 if (r.IsDouble()) { |
| 3453 XMMRegister scratch = xmm0; | 3452 XMMRegister scratch = xmm0; |
| 3454 XMMRegister input_reg = ToDoubleRegister(instr->value()); | 3453 XMMRegister input_reg = ToDoubleRegister(instr->value()); |
| 3455 __ xorps(scratch, scratch); | 3454 __ xorps(scratch, scratch); |
| 3456 __ subsd(scratch, input_reg); | 3455 __ subsd(scratch, input_reg); |
| 3457 __ andpd(input_reg, scratch); | 3456 __ andpd(input_reg, scratch); |
| 3458 } else if (r.IsInteger32()) { | 3457 } else if (r.IsInteger32()) { |
| 3459 EmitIntegerMathAbs(instr); | 3458 EmitIntegerMathAbs(instr); |
| 3460 } else { // Tagged case. | 3459 } else { // Tagged case. |
| 3461 DeferredMathAbsTaggedHeapNumber* deferred = | 3460 DeferredMathAbsTaggedHeapNumber* deferred = |
| 3462 new(zone()) DeferredMathAbsTaggedHeapNumber(this, instr); | 3461 new(zone()) DeferredMathAbsTaggedHeapNumber(this, instr); |
| 3463 Register input_reg = ToRegister(instr->value()); | 3462 Register input_reg = ToRegister(instr->value()); |
| 3464 // Smi check. | 3463 // Smi check. |
| 3465 __ JumpIfNotSmi(input_reg, deferred->entry()); | 3464 __ JumpIfNotSmi(input_reg, deferred->entry()); |
| 3466 __ SmiToInteger32(input_reg, input_reg); | 3465 __ SmiToInteger32(input_reg, input_reg); |
| 3467 EmitIntegerMathAbs(instr); | 3466 EmitIntegerMathAbs(instr); |
| 3468 __ Integer32ToSmi(input_reg, input_reg); | 3467 __ Integer32ToSmi(input_reg, input_reg); |
| 3469 __ bind(deferred->exit()); | 3468 __ bind(deferred->exit()); |
| 3470 } | 3469 } |
| 3471 } | 3470 } |
| 3472 | 3471 |
| 3473 | 3472 |
| 3474 void LCodeGen::DoMathFloor(LUnaryMathOperation* instr) { | 3473 void LCodeGen::DoMathFloor(LMathFloor* instr) { |
| 3475 XMMRegister xmm_scratch = xmm0; | 3474 XMMRegister xmm_scratch = xmm0; |
| 3476 Register output_reg = ToRegister(instr->result()); | 3475 Register output_reg = ToRegister(instr->result()); |
| 3477 XMMRegister input_reg = ToDoubleRegister(instr->value()); | 3476 XMMRegister input_reg = ToDoubleRegister(instr->value()); |
| 3478 | 3477 |
| 3479 if (CpuFeatures::IsSupported(SSE4_1)) { | 3478 if (CpuFeatures::IsSupported(SSE4_1)) { |
| 3480 CpuFeatureScope scope(masm(), SSE4_1); | 3479 CpuFeatureScope scope(masm(), SSE4_1); |
| 3481 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { | 3480 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { |
| 3482 // Deoptimize if minus zero. | 3481 // Deoptimize if minus zero. |
| 3483 __ movq(output_reg, input_reg); | 3482 __ movq(output_reg, input_reg); |
| 3484 __ subq(output_reg, Immediate(1)); | 3483 __ subq(output_reg, Immediate(1)); |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3523 __ ucomisd(input_reg, xmm_scratch); | 3522 __ ucomisd(input_reg, xmm_scratch); |
| 3524 __ j(equal, &done, Label::kNear); | 3523 __ j(equal, &done, Label::kNear); |
| 3525 __ subl(output_reg, Immediate(1)); | 3524 __ subl(output_reg, Immediate(1)); |
| 3526 DeoptimizeIf(overflow, instr->environment()); | 3525 DeoptimizeIf(overflow, instr->environment()); |
| 3527 | 3526 |
| 3528 __ bind(&done); | 3527 __ bind(&done); |
| 3529 } | 3528 } |
| 3530 } | 3529 } |
| 3531 | 3530 |
| 3532 | 3531 |
| 3533 void LCodeGen::DoMathRound(LUnaryMathOperation* instr) { | 3532 void LCodeGen::DoMathRound(LMathRound* instr) { |
| 3534 const XMMRegister xmm_scratch = xmm0; | 3533 const XMMRegister xmm_scratch = xmm0; |
| 3535 Register output_reg = ToRegister(instr->result()); | 3534 Register output_reg = ToRegister(instr->result()); |
| 3536 XMMRegister input_reg = ToDoubleRegister(instr->value()); | 3535 XMMRegister input_reg = ToDoubleRegister(instr->value()); |
| 3537 static int64_t one_half = V8_INT64_C(0x3FE0000000000000); // 0.5 | 3536 static int64_t one_half = V8_INT64_C(0x3FE0000000000000); // 0.5 |
| 3538 static int64_t minus_one_half = V8_INT64_C(0xBFE0000000000000); // -0.5 | 3537 static int64_t minus_one_half = V8_INT64_C(0xBFE0000000000000); // -0.5 |
| 3539 | 3538 |
| 3540 Label done, round_to_zero, below_one_half, do_not_compensate, restore; | 3539 Label done, round_to_zero, below_one_half, do_not_compensate, restore; |
| 3541 __ movq(kScratchRegister, one_half, RelocInfo::NONE64); | 3540 __ movq(kScratchRegister, one_half, RelocInfo::NONE64); |
| 3542 __ movq(xmm_scratch, kScratchRegister); | 3541 __ movq(xmm_scratch, kScratchRegister); |
| 3543 __ ucomisd(xmm_scratch, input_reg); | 3542 __ ucomisd(xmm_scratch, input_reg); |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3584 __ movq(output_reg, input_reg); | 3583 __ movq(output_reg, input_reg); |
| 3585 __ testq(output_reg, output_reg); | 3584 __ testq(output_reg, output_reg); |
| 3586 __ RecordComment("Minus zero"); | 3585 __ RecordComment("Minus zero"); |
| 3587 DeoptimizeIf(negative, instr->environment()); | 3586 DeoptimizeIf(negative, instr->environment()); |
| 3588 } | 3587 } |
| 3589 __ Set(output_reg, 0); | 3588 __ Set(output_reg, 0); |
| 3590 __ bind(&done); | 3589 __ bind(&done); |
| 3591 } | 3590 } |
| 3592 | 3591 |
| 3593 | 3592 |
| 3594 void LCodeGen::DoMathSqrt(LUnaryMathOperation* instr) { | 3593 void LCodeGen::DoMathSqrt(LMathSqrt* instr) { |
| 3595 XMMRegister input_reg = ToDoubleRegister(instr->value()); | 3594 XMMRegister input_reg = ToDoubleRegister(instr->value()); |
| 3596 ASSERT(ToDoubleRegister(instr->result()).is(input_reg)); | 3595 ASSERT(ToDoubleRegister(instr->result()).is(input_reg)); |
| 3597 __ sqrtsd(input_reg, input_reg); | 3596 __ sqrtsd(input_reg, input_reg); |
| 3598 } | 3597 } |
| 3599 | 3598 |
| 3600 | 3599 |
| 3601 void LCodeGen::DoMathPowHalf(LUnaryMathOperation* instr) { | 3600 void LCodeGen::DoMathPowHalf(LMathPowHalf* instr) { |
| 3602 XMMRegister xmm_scratch = xmm0; | 3601 XMMRegister xmm_scratch = xmm0; |
| 3603 XMMRegister input_reg = ToDoubleRegister(instr->value()); | 3602 XMMRegister input_reg = ToDoubleRegister(instr->value()); |
| 3604 ASSERT(ToDoubleRegister(instr->result()).is(input_reg)); | 3603 ASSERT(ToDoubleRegister(instr->result()).is(input_reg)); |
| 3605 | 3604 |
| 3606 // Note that according to ECMA-262 15.8.2.13: | 3605 // Note that according to ECMA-262 15.8.2.13: |
| 3607 // Math.pow(-Infinity, 0.5) == Infinity | 3606 // Math.pow(-Infinity, 0.5) == Infinity |
| 3608 // Math.sqrt(-Infinity) == NaN | 3607 // Math.sqrt(-Infinity) == NaN |
| 3609 Label done, sqrt; | 3608 Label done, sqrt; |
| 3610 // Check base for -Infinity. According to IEEE-754, double-precision | 3609 // Check base for -Infinity. According to IEEE-754, double-precision |
| 3611 // -Infinity has the highest 12 bits set and the lowest 52 bits cleared. | 3610 // -Infinity has the highest 12 bits set and the lowest 52 bits cleared. |
| (...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3758 void LCodeGen::DoMathExp(LMathExp* instr) { | 3757 void LCodeGen::DoMathExp(LMathExp* instr) { |
| 3759 XMMRegister input = ToDoubleRegister(instr->value()); | 3758 XMMRegister input = ToDoubleRegister(instr->value()); |
| 3760 XMMRegister result = ToDoubleRegister(instr->result()); | 3759 XMMRegister result = ToDoubleRegister(instr->result()); |
| 3761 Register temp1 = ToRegister(instr->temp1()); | 3760 Register temp1 = ToRegister(instr->temp1()); |
| 3762 Register temp2 = ToRegister(instr->temp2()); | 3761 Register temp2 = ToRegister(instr->temp2()); |
| 3763 | 3762 |
| 3764 MathExpGenerator::EmitMathExp(masm(), input, result, xmm0, temp1, temp2); | 3763 MathExpGenerator::EmitMathExp(masm(), input, result, xmm0, temp1, temp2); |
| 3765 } | 3764 } |
| 3766 | 3765 |
| 3767 | 3766 |
| 3768 void LCodeGen::DoMathLog(LUnaryMathOperation* instr) { | 3767 void LCodeGen::DoMathLog(LMathLog* instr) { |
| 3769 ASSERT(ToDoubleRegister(instr->result()).is(xmm1)); | 3768 ASSERT(ToDoubleRegister(instr->result()).is(xmm1)); |
| 3770 TranscendentalCacheStub stub(TranscendentalCache::LOG, | 3769 TranscendentalCacheStub stub(TranscendentalCache::LOG, |
| 3771 TranscendentalCacheStub::UNTAGGED); | 3770 TranscendentalCacheStub::UNTAGGED); |
| 3772 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr); | 3771 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr); |
| 3773 } | 3772 } |
| 3774 | 3773 |
| 3775 | 3774 |
| 3776 void LCodeGen::DoMathTan(LUnaryMathOperation* instr) { | 3775 void LCodeGen::DoMathTan(LMathTan* instr) { |
| 3777 ASSERT(ToDoubleRegister(instr->result()).is(xmm1)); | 3776 ASSERT(ToDoubleRegister(instr->result()).is(xmm1)); |
| 3778 TranscendentalCacheStub stub(TranscendentalCache::TAN, | 3777 TranscendentalCacheStub stub(TranscendentalCache::TAN, |
| 3779 TranscendentalCacheStub::UNTAGGED); | 3778 TranscendentalCacheStub::UNTAGGED); |
| 3780 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr); | 3779 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr); |
| 3781 } | 3780 } |
| 3782 | 3781 |
| 3783 | 3782 |
| 3784 void LCodeGen::DoMathCos(LUnaryMathOperation* instr) { | 3783 void LCodeGen::DoMathCos(LMathCos* instr) { |
| 3785 ASSERT(ToDoubleRegister(instr->result()).is(xmm1)); | 3784 ASSERT(ToDoubleRegister(instr->result()).is(xmm1)); |
| 3786 TranscendentalCacheStub stub(TranscendentalCache::COS, | 3785 TranscendentalCacheStub stub(TranscendentalCache::COS, |
| 3787 TranscendentalCacheStub::UNTAGGED); | 3786 TranscendentalCacheStub::UNTAGGED); |
| 3788 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr); | 3787 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr); |
| 3789 } | 3788 } |
| 3790 | 3789 |
| 3791 | 3790 |
| 3792 void LCodeGen::DoMathSin(LUnaryMathOperation* instr) { | 3791 void LCodeGen::DoMathSin(LMathSin* instr) { |
| 3793 ASSERT(ToDoubleRegister(instr->result()).is(xmm1)); | 3792 ASSERT(ToDoubleRegister(instr->result()).is(xmm1)); |
| 3794 TranscendentalCacheStub stub(TranscendentalCache::SIN, | 3793 TranscendentalCacheStub stub(TranscendentalCache::SIN, |
| 3795 TranscendentalCacheStub::UNTAGGED); | 3794 TranscendentalCacheStub::UNTAGGED); |
| 3796 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr); | 3795 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr); |
| 3797 } | 3796 } |
| 3798 | 3797 |
| 3799 | 3798 |
| 3800 void LCodeGen::DoUnaryMathOperation(LUnaryMathOperation* instr) { | |
| 3801 switch (instr->op()) { | |
| 3802 case kMathAbs: | |
| 3803 DoMathAbs(instr); | |
| 3804 break; | |
| 3805 case kMathFloor: | |
| 3806 DoMathFloor(instr); | |
| 3807 break; | |
| 3808 case kMathRound: | |
| 3809 DoMathRound(instr); | |
| 3810 break; | |
| 3811 case kMathSqrt: | |
| 3812 DoMathSqrt(instr); | |
| 3813 break; | |
| 3814 case kMathPowHalf: | |
| 3815 DoMathPowHalf(instr); | |
| 3816 break; | |
| 3817 case kMathCos: | |
| 3818 DoMathCos(instr); | |
| 3819 break; | |
| 3820 case kMathSin: | |
| 3821 DoMathSin(instr); | |
| 3822 break; | |
| 3823 case kMathTan: | |
| 3824 DoMathTan(instr); | |
| 3825 break; | |
| 3826 case kMathLog: | |
| 3827 DoMathLog(instr); | |
| 3828 break; | |
| 3829 | |
| 3830 default: | |
| 3831 UNREACHABLE(); | |
| 3832 } | |
| 3833 } | |
| 3834 | |
| 3835 | |
| 3836 void LCodeGen::DoInvokeFunction(LInvokeFunction* instr) { | 3799 void LCodeGen::DoInvokeFunction(LInvokeFunction* instr) { |
| 3837 ASSERT(ToRegister(instr->function()).is(rdi)); | 3800 ASSERT(ToRegister(instr->function()).is(rdi)); |
| 3838 ASSERT(instr->HasPointerMap()); | 3801 ASSERT(instr->HasPointerMap()); |
| 3839 | 3802 |
| 3840 if (instr->known_function().is_null()) { | 3803 if (instr->known_function().is_null()) { |
| 3841 LPointerMap* pointers = instr->pointer_map(); | 3804 LPointerMap* pointers = instr->pointer_map(); |
| 3842 RecordPosition(pointers->position()); | 3805 RecordPosition(pointers->position()); |
| 3843 SafepointGenerator generator(this, pointers, Safepoint::kLazyDeopt); | 3806 SafepointGenerator generator(this, pointers, Safepoint::kLazyDeopt); |
| 3844 ParameterCount count(instr->arity()); | 3807 ParameterCount count(instr->arity()); |
| 3845 __ InvokeFunction(rdi, count, CALL_FUNCTION, generator, CALL_AS_METHOD); | 3808 __ InvokeFunction(rdi, count, CALL_FUNCTION, generator, CALL_AS_METHOD); |
| (...skipping 1844 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5690 FixedArray::kHeaderSize - kPointerSize)); | 5653 FixedArray::kHeaderSize - kPointerSize)); |
| 5691 __ bind(&done); | 5654 __ bind(&done); |
| 5692 } | 5655 } |
| 5693 | 5656 |
| 5694 | 5657 |
| 5695 #undef __ | 5658 #undef __ |
| 5696 | 5659 |
| 5697 } } // namespace v8::internal | 5660 } } // namespace v8::internal |
| 5698 | 5661 |
| 5699 #endif // V8_TARGET_ARCH_X64 | 5662 #endif // V8_TARGET_ARCH_X64 |
| OLD | NEW |