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

Side by Side Diff: src/x64/codegen-x64.cc

Issue 1851002: X64: Minor change of control flow in inline transcendental cache. (Closed)
Patch Set: Created 10 years, 7 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/x64/codegen-x64.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2010 the V8 project authors. All rights reserved. 1 // Copyright 2010 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 25 matching lines...) Expand all
36 #include "regexp-macro-assembler.h" 36 #include "regexp-macro-assembler.h"
37 #include "register-allocator-inl.h" 37 #include "register-allocator-inl.h"
38 #include "scopes.h" 38 #include "scopes.h"
39 #include "virtual-frame-inl.h" 39 #include "virtual-frame-inl.h"
40 40
41 namespace v8 { 41 namespace v8 {
42 namespace internal { 42 namespace internal {
43 43
44 #define __ ACCESS_MASM(masm_) 44 #define __ ACCESS_MASM(masm_)
45 45
46 static int64_t kNaNValue = V8_INT64_C(0x7ff8000000000000);
47
48 // ------------------------------------------------------------------------- 46 // -------------------------------------------------------------------------
49 // Platform-specific DeferredCode functions. 47 // Platform-specific DeferredCode functions.
50 48
51 void DeferredCode::SaveRegisters() { 49 void DeferredCode::SaveRegisters() {
52 for (int i = 0; i < RegisterAllocator::kNumRegisters; i++) { 50 for (int i = 0; i < RegisterAllocator::kNumRegisters; i++) {
53 int action = registers_[i]; 51 int action = registers_[i];
54 if (action == kPush) { 52 if (action == kPush) {
55 __ push(RegisterAllocator::ToRegister(i)); 53 __ push(RegisterAllocator::ToRegister(i));
56 } else if (action != kIgnore && (action & kSyncedFlag) == 0) { 54 } else if (action != kIgnore && (action & kSyncedFlag) == 0) {
57 __ movq(Operand(rbp, action), RegisterAllocator::ToRegister(i)); 55 __ movq(Operand(rbp, action), RegisterAllocator::ToRegister(i));
(...skipping 7492 matching lines...) Expand 10 before | Expand all | Expand 10 after
7550 Label cache_miss; 7548 Label cache_miss;
7551 __ cmpq(rbx, Operand(rcx, 0)); 7549 __ cmpq(rbx, Operand(rcx, 0));
7552 __ j(not_equal, &cache_miss); 7550 __ j(not_equal, &cache_miss);
7553 // Cache hit! 7551 // Cache hit!
7554 __ movq(rax, Operand(rcx, 2 * kIntSize)); 7552 __ movq(rax, Operand(rcx, 2 * kIntSize));
7555 __ fstp(0); // Clear FPU stack. 7553 __ fstp(0); // Clear FPU stack.
7556 __ ret(kPointerSize); 7554 __ ret(kPointerSize);
7557 7555
7558 __ bind(&cache_miss); 7556 __ bind(&cache_miss);
7559 // Update cache with new value. 7557 // Update cache with new value.
7558 Label nan_result;
7559 GenerateOperation(masm, &nan_result);
7560 __ AllocateHeapNumber(rax, rdi, &runtime_call_clear_stack); 7560 __ AllocateHeapNumber(rax, rdi, &runtime_call_clear_stack);
7561 GenerateOperation(masm);
7562 __ movq(Operand(rcx, 0), rbx); 7561 __ movq(Operand(rcx, 0), rbx);
7563 __ movq(Operand(rcx, 2 * kIntSize), rax); 7562 __ movq(Operand(rcx, 2 * kIntSize), rax);
7564 __ fstp_d(FieldOperand(rax, HeapNumber::kValueOffset)); 7563 __ fstp_d(FieldOperand(rax, HeapNumber::kValueOffset));
7565 __ ret(kPointerSize); 7564 __ ret(kPointerSize);
7566 7565
7567 __ bind(&runtime_call_clear_stack); 7566 __ bind(&runtime_call_clear_stack);
7568 __ fstp(0); 7567 __ fstp(0);
7569 __ bind(&runtime_call); 7568 __ bind(&runtime_call);
7570 __ TailCallExternalReference(ExternalReference(RuntimeFunction()), 1, 1); 7569 __ TailCallExternalReference(ExternalReference(RuntimeFunction()), 1, 1);
7570
7571 __ bind(&nan_result);
7572 __ fstp(0); // Remove argument from FPU stack.
7573 __ LoadRoot(rax, Heap::kNanValueRootIndex);
7574 __ movq(Operand(rcx, 0), rbx);
7575 __ movq(Operand(rcx, 2 * kIntSize), rax);
7576 __ ret(kPointerSize);
7571 } 7577 }
7572 7578
7573 7579
7574 Runtime::FunctionId TranscendentalCacheStub::RuntimeFunction() { 7580 Runtime::FunctionId TranscendentalCacheStub::RuntimeFunction() {
7575 switch (type_) { 7581 switch (type_) {
7576 // Add more cases when necessary. 7582 // Add more cases when necessary.
7577 case TranscendentalCache::SIN: return Runtime::kMath_sin; 7583 case TranscendentalCache::SIN: return Runtime::kMath_sin;
7578 case TranscendentalCache::COS: return Runtime::kMath_cos; 7584 case TranscendentalCache::COS: return Runtime::kMath_cos;
7579 default: 7585 default:
7580 UNIMPLEMENTED(); 7586 UNIMPLEMENTED();
7581 return Runtime::kAbort; 7587 return Runtime::kAbort;
7582 } 7588 }
7583 } 7589 }
7584 7590
7585 7591
7586 void TranscendentalCacheStub::GenerateOperation(MacroAssembler* masm) { 7592 void TranscendentalCacheStub::GenerateOperation(MacroAssembler* masm,
7587 // Only free register is rdi. 7593 Label* on_nan_result) {
7594 // Registers:
7595 // rbx: Bits of input double. Must be preserved.
7596 // rcx: Pointer to cache entry. Must be preserved.
7597 // st(0): Input double
7588 Label done; 7598 Label done;
7589 ASSERT(type_ == TranscendentalCache::SIN || 7599 ASSERT(type_ == TranscendentalCache::SIN ||
7590 type_ == TranscendentalCache::COS); 7600 type_ == TranscendentalCache::COS);
7591 // More transcendental types can be added later. 7601 // More transcendental types can be added later.
7592 7602
7593 // Both fsin and fcos require arguments in the range +/-2^63 and 7603 // Both fsin and fcos require arguments in the range +/-2^63 and
7594 // return NaN for infinities and NaN. They can share all code except 7604 // return NaN for infinities and NaN. They can share all code except
7595 // the actual fsin/fcos operation. 7605 // the actual fsin/fcos operation.
7596 Label in_range; 7606 Label in_range;
7597 // If argument is outside the range -2^63..2^63, fsin/cos doesn't 7607 // If argument is outside the range -2^63..2^63, fsin/cos doesn't
7598 // work. We must reduce it to the appropriate range. 7608 // work. We must reduce it to the appropriate range.
7599 __ movq(rdi, rbx); 7609 __ movq(rdi, rbx);
7600 // Move exponent and sign bits to low bits. 7610 // Move exponent and sign bits to low bits.
7601 __ shr(rdi, Immediate(HeapNumber::kMantissaBits)); 7611 __ shr(rdi, Immediate(HeapNumber::kMantissaBits));
7602 // Remove sign bit. 7612 // Remove sign bit.
7603 __ andl(rdi, Immediate((1 << HeapNumber::KExponentBits) - 1)); 7613 __ andl(rdi, Immediate((1 << HeapNumber::KExponentBits) - 1));
7604 int supported_exponent_limit = (63 + HeapNumber::kExponentBias); 7614 int supported_exponent_limit = (63 + HeapNumber::kExponentBias);
7605 __ cmpl(rdi, Immediate(supported_exponent_limit)); 7615 __ cmpl(rdi, Immediate(supported_exponent_limit));
7606 __ j(below, &in_range); 7616 __ j(below, &in_range);
7607 // Check for infinity and NaN. Both return NaN for sin. 7617 // Check for infinity and NaN. Both return NaN for sin.
7608 __ cmpl(rdi, Immediate(0x7ff)); 7618 __ cmpl(rdi, Immediate(0x7ff));
7609 Label non_nan_result; 7619 __ j(equal, on_nan_result);
7610 __ j(not_equal, &non_nan_result);
7611 // Input is +/-Infinity or NaN. Result is NaN.
7612 __ fstp(0); // Clear fpu stack.
7613 // NaN is represented by 0x7ff8000000000000.
7614 __ movq(rdi, kNaNValue, RelocInfo::NONE);
7615 __ push(rdi);
7616 __ fld_d(Operand(rsp, 0));
7617 __ addq(rsp, Immediate(kPointerSize));
7618 __ jmp(&done);
7619
7620 __ bind(&non_nan_result);
7621 7620
7622 // Use fpmod to restrict argument to the range +/-2*PI. 7621 // Use fpmod to restrict argument to the range +/-2*PI.
7623 __ movq(rdi, rax); // Save rax before using fnstsw_ax.
7624 __ fldpi(); 7622 __ fldpi();
7625 __ fadd(0); 7623 __ fadd(0);
7626 __ fld(1); 7624 __ fld(1);
7627 // FPU Stack: input, 2*pi, input. 7625 // FPU Stack: input, 2*pi, input.
7628 { 7626 {
7629 Label no_exceptions; 7627 Label no_exceptions;
7630 __ fwait(); 7628 __ fwait();
7631 __ fnstsw_ax(); 7629 __ fnstsw_ax();
7632 // Clear if Illegal Operand or Zero Division exceptions are set. 7630 // Clear if Illegal Operand or Zero Division exceptions are set.
7633 __ testl(rax, Immediate(5)); 7631 __ testl(rax, Immediate(5)); // #IO and #ZD flags of FPU status word.
7634 __ j(zero, &no_exceptions); 7632 __ j(zero, &no_exceptions);
7635 __ fnclex(); 7633 __ fnclex();
7636 __ bind(&no_exceptions); 7634 __ bind(&no_exceptions);
7637 } 7635 }
7638 7636
7639 // Compute st(0) % st(1) 7637 // Compute st(0) % st(1)
7640 { 7638 {
7641 Label partial_remainder_loop; 7639 Label partial_remainder_loop;
7642 __ bind(&partial_remainder_loop); 7640 __ bind(&partial_remainder_loop);
7643 __ fprem1(); 7641 __ fprem1();
7644 __ fwait(); 7642 __ fwait();
7645 __ fnstsw_ax(); 7643 __ fnstsw_ax();
7646 __ testl(rax, Immediate(0x400)); // Check C2 bit of FPU status word. 7644 __ testl(rax, Immediate(0x400)); // Check C2 bit of FPU status word.
7647 // If C2 is set, computation only has partial result. Loop to 7645 // If C2 is set, computation only has partial result. Loop to
7648 // continue computation. 7646 // continue computation.
7649 __ j(not_zero, &partial_remainder_loop); 7647 __ j(not_zero, &partial_remainder_loop);
7650 } 7648 }
7651 // FPU Stack: input, 2*pi, input % 2*pi 7649 // FPU Stack: input, 2*pi, input % 2*pi
7652 __ fstp(2); 7650 __ fstp(2);
7653 // FPU Stack: input % 2*pi, 2*pi, 7651 // FPU Stack: input % 2*pi, 2*pi,
7654 __ fstp(0); 7652 __ fstp(0);
7655 // FPU Stack: input % 2*pi 7653 // FPU Stack: input % 2*pi
7656 __ movq(rax, rdi); // Restore rax (allocated HeapNumber pointer).
7657
7658 // FPU Stack: input % 2*pi
7659 __ bind(&in_range); 7654 __ bind(&in_range);
7660 switch (type_) { 7655 switch (type_) {
7661 case TranscendentalCache::SIN: 7656 case TranscendentalCache::SIN:
7662 __ fsin(); 7657 __ fsin();
7663 break; 7658 break;
7664 case TranscendentalCache::COS: 7659 case TranscendentalCache::COS:
7665 __ fcos(); 7660 __ fcos();
7666 break; 7661 break;
7667 default: 7662 default:
7668 UNREACHABLE(); 7663 UNREACHABLE();
(...skipping 3531 matching lines...) Expand 10 before | Expand all | Expand 10 after
11200 __ j(not_zero, &partial_remainder_loop); 11195 __ j(not_zero, &partial_remainder_loop);
11201 } 11196 }
11202 11197
11203 Label valid_result; 11198 Label valid_result;
11204 Label return_result; 11199 Label return_result;
11205 // If Invalid Operand or Zero Division exceptions are set, 11200 // If Invalid Operand or Zero Division exceptions are set,
11206 // return NaN. 11201 // return NaN.
11207 __ testb(rax, Immediate(5)); 11202 __ testb(rax, Immediate(5));
11208 __ j(zero, &valid_result); 11203 __ j(zero, &valid_result);
11209 __ fstp(0); // Drop result in st(0). 11204 __ fstp(0); // Drop result in st(0).
11205 int64_t kNaNValue = V8_INT64_C(0x7ff8000000000000);
11210 __ movq(rcx, kNaNValue, RelocInfo::NONE); 11206 __ movq(rcx, kNaNValue, RelocInfo::NONE);
11211 __ movq(Operand(rsp, kPointerSize), rcx); 11207 __ movq(Operand(rsp, kPointerSize), rcx);
11212 __ movsd(xmm0, Operand(rsp, kPointerSize)); 11208 __ movsd(xmm0, Operand(rsp, kPointerSize));
11213 __ jmp(&return_result); 11209 __ jmp(&return_result);
11214 11210
11215 // If result is valid, return that. 11211 // If result is valid, return that.
11216 __ bind(&valid_result); 11212 __ bind(&valid_result);
11217 __ fstp_d(Operand(rsp, kPointerSize)); 11213 __ fstp_d(Operand(rsp, kPointerSize));
11218 __ movsd(xmm0, Operand(rsp, kPointerSize)); 11214 __ movsd(xmm0, Operand(rsp, kPointerSize));
11219 11215
(...skipping 14 matching lines...) Expand all
11234 // Call the function from C++. 11230 // Call the function from C++.
11235 return FUNCTION_CAST<ModuloFunction>(buffer); 11231 return FUNCTION_CAST<ModuloFunction>(buffer);
11236 } 11232 }
11237 11233
11238 #endif 11234 #endif
11239 11235
11240 11236
11241 #undef __ 11237 #undef __
11242 11238
11243 } } // namespace v8::internal 11239 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/x64/codegen-x64.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698