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 |