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

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

Issue 5726008: Reapply change 5989, adding untagged double calls to Math.pow, with problem i... (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: Created 10 years 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 | Annotate | Revision Log
« no previous file with comments | « src/ia32/code-stubs-ia32.h ('k') | src/ia32/disasm-ia32.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 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 2665 matching lines...) Expand 10 before | Expand all | Expand 10 after
2676 __ bind(&done); 2676 __ bind(&done);
2677 } else { 2677 } else {
2678 ASSERT(type_ == TranscendentalCache::LOG); 2678 ASSERT(type_ == TranscendentalCache::LOG);
2679 __ fldln2(); 2679 __ fldln2();
2680 __ fxch(); 2680 __ fxch();
2681 __ fyl2x(); 2681 __ fyl2x();
2682 } 2682 }
2683 } 2683 }
2684 2684
2685 2685
2686 void TranscendentalCacheSSE2Stub::Generate(MacroAssembler* masm) {
2687 // Input on stack:
2688 // esp[0]: return address.
2689 // Input in registers:
2690 // xmm1: untagged double input argument.
2691 // Output:
2692 // xmm1: untagged double result.
2693 Label skip_cache;
2694 Label call_runtime;
2695
2696 // Input is an untagged double in xmm1.
2697 // Compute hash (the shifts are arithmetic):
2698 // h = (low ^ high); h ^= h >> 16; h ^= h >> 8; h = h & (cacheSize - 1);
2699 if (CpuFeatures::IsSupported(SSE4_1)) {
2700 CpuFeatures::Scope sse4_scope(SSE4_1);
2701 __ pextrd(Operand(edx), xmm1, 0x1); // copy xmm1[63..32] to edx.
2702 } else {
2703 __ pshufd(xmm0, xmm1, 0x1);
2704 __ movd(Operand(edx), xmm0);
2705 }
2706 __ movd(Operand(ebx), xmm1);
2707
2708 // xmm1 = double value
2709 // ebx = low 32 bits of double value
2710 // edx = high 32 bits of double value
2711 // Compute hash (the shifts are arithmetic):
2712 // h = (low ^ high); h ^= h >> 16; h ^= h >> 8; h = h & (cacheSize - 1);
2713 __ mov(ecx, ebx);
2714 __ xor_(ecx, Operand(edx));
2715 __ mov(eax, ecx);
2716 __ sar(eax, 16);
2717 __ xor_(ecx, Operand(eax));
2718 __ mov(eax, ecx);
2719 __ sar(eax, 8);
2720 __ xor_(ecx, Operand(eax));
2721 ASSERT(IsPowerOf2(TranscendentalCache::kCacheSize));
2722 __ and_(Operand(ecx), Immediate(TranscendentalCache::kCacheSize - 1));
2723
2724 // xmm1 = double value.
2725 // ebx = low 32 bits of double value.
2726 // edx = high 32 bits of double value.
2727 // ecx = TranscendentalCache::hash(double value).
2728 __ mov(eax,
2729 Immediate(ExternalReference::transcendental_cache_array_address()));
2730 // Eax points to cache array.
2731 __ mov(eax, Operand(eax, type_ * sizeof(TranscendentalCache::caches_[0])));
2732 // Eax points to the cache for the type type_.
2733 // If NULL, the cache hasn't been initialized yet, so go through runtime.
2734 __ test(eax, Operand(eax));
2735 __ j(zero, &call_runtime);
2736 #ifdef DEBUG
2737 // Check that the layout of cache elements match expectations.
2738 { TranscendentalCache::Element test_elem[2];
2739 char* elem_start = reinterpret_cast<char*>(&test_elem[0]);
2740 char* elem2_start = reinterpret_cast<char*>(&test_elem[1]);
2741 char* elem_in0 = reinterpret_cast<char*>(&(test_elem[0].in[0]));
2742 char* elem_in1 = reinterpret_cast<char*>(&(test_elem[0].in[1]));
2743 char* elem_out = reinterpret_cast<char*>(&(test_elem[0].output));
2744 CHECK_EQ(12, elem2_start - elem_start); // Two uint_32's and a pointer.
2745 CHECK_EQ(0, elem_in0 - elem_start);
2746 CHECK_EQ(kIntSize, elem_in1 - elem_start);
2747 CHECK_EQ(2 * kIntSize, elem_out - elem_start);
2748 }
2749 #endif
2750 // Find the address of the ecx'th entry in the cache, i.e., &eax[ecx*12].
2751 __ lea(ecx, Operand(ecx, ecx, times_2, 0));
2752 __ lea(ecx, Operand(eax, ecx, times_4, 0));
2753 // Check if cache matches: Double value is stored in uint32_t[2] array.
2754 NearLabel cache_miss;
2755 __ cmp(ebx, Operand(ecx, 0));
2756 __ j(not_equal, &cache_miss);
2757 __ cmp(edx, Operand(ecx, kIntSize));
2758 __ j(not_equal, &cache_miss);
2759 // Cache hit!
2760 __ mov(eax, Operand(ecx, 2 * kIntSize));
2761 __ movdbl(xmm1, FieldOperand(eax, HeapNumber::kValueOffset));
2762 __ Ret();
2763
2764 __ bind(&cache_miss);
2765 // Update cache with new value.
2766 // We are short on registers, so use no_reg as scratch.
2767 // This gives slightly larger code.
2768 __ AllocateHeapNumber(eax, edi, no_reg, &skip_cache);
2769 __ sub(Operand(esp), Immediate(kDoubleSize));
2770 __ movdbl(Operand(esp, 0), xmm1);
2771 __ fld_d(Operand(esp, 0));
2772 __ add(Operand(esp), Immediate(kDoubleSize));
2773 GenerateOperation(masm);
2774 __ mov(Operand(ecx, 0), ebx);
2775 __ mov(Operand(ecx, kIntSize), edx);
2776 __ mov(Operand(ecx, 2 * kIntSize), eax);
2777 __ fstp_d(FieldOperand(eax, HeapNumber::kValueOffset));
2778 __ movdbl(xmm1, FieldOperand(eax, HeapNumber::kValueOffset));
2779 __ Ret();
2780
2781 __ bind(&skip_cache);
2782 __ sub(Operand(esp), Immediate(kDoubleSize));
2783 __ movdbl(Operand(esp, 0), xmm1);
2784 __ fld_d(Operand(esp, 0));
2785 GenerateOperation(masm);
2786 __ fstp_d(Operand(esp, 0));
2787 __ movdbl(xmm1, Operand(esp, 0));
2788 __ add(Operand(esp), Immediate(kDoubleSize));
2789 __ Ret();
2790
2791 __ bind(&call_runtime);
2792 __ AllocateHeapNumber(eax, edi, no_reg, &skip_cache);
2793 __ push(eax);
2794 __ movdbl(FieldOperand(eax, HeapNumber::kValueOffset), xmm1);
2795 __ CallRuntime(RuntimeFunction(), 1);
2796 __ movdbl(xmm1, FieldOperand(eax, HeapNumber::kValueOffset));
2797 __ Ret();
2798 }
2799
2800
2801 Runtime::FunctionId TranscendentalCacheSSE2Stub::RuntimeFunction() {
2802 switch (type_) {
2803 // Add more cases when necessary.
2804 case TranscendentalCache::LOG: return Runtime::kMath_log;
2805 default:
2806 UNIMPLEMENTED();
2807 return Runtime::kAbort;
2808 }
2809 }
2810
2811
2812 void TranscendentalCacheSSE2Stub::GenerateOperation(MacroAssembler* masm) {
2813 // Only free register is edi.
2814 // Input value is on FP stack and in xmm1.
2815
2816 ASSERT(type_ == TranscendentalCache::LOG);
2817 __ fldln2();
2818 __ fxch();
2819 __ fyl2x();
2820 }
2821
2822
2686 // Get the integer part of a heap number. Surprisingly, all this bit twiddling 2823 // Get the integer part of a heap number. Surprisingly, all this bit twiddling
2687 // is faster than using the built-in instructions on floating point registers. 2824 // is faster than using the built-in instructions on floating point registers.
2688 // Trashes edi and ebx. Dest is ecx. Source cannot be ecx or one of the 2825 // Trashes edi and ebx. Dest is ecx. Source cannot be ecx or one of the
2689 // trashed registers. 2826 // trashed registers.
2690 void IntegerConvert(MacroAssembler* masm, 2827 void IntegerConvert(MacroAssembler* masm,
2691 Register source, 2828 Register source,
2692 TypeInfo type_info, 2829 TypeInfo type_info,
2693 bool use_sse3, 2830 bool use_sse3,
2694 Label* conversion_failure) { 2831 Label* conversion_failure) {
2695 ASSERT(!source.is(ecx) && !source.is(edi) && !source.is(ebx)); 2832 ASSERT(!source.is(ecx) && !source.is(edi) && !source.is(ebx));
(...skipping 3587 matching lines...) Expand 10 before | Expand all | Expand 10 after
6283 // Do a tail call to the rewritten stub. 6420 // Do a tail call to the rewritten stub.
6284 __ jmp(Operand(edi)); 6421 __ jmp(Operand(edi));
6285 } 6422 }
6286 6423
6287 6424
6288 #undef __ 6425 #undef __
6289 6426
6290 } } // namespace v8::internal 6427 } } // namespace v8::internal
6291 6428
6292 #endif // V8_TARGET_ARCH_IA32 6429 #endif // V8_TARGET_ARCH_IA32
OLDNEW
« no previous file with comments | « src/ia32/code-stubs-ia32.h ('k') | src/ia32/disasm-ia32.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698