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

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

Issue 5741003: Allow optimizing compiler to compute Math.log using untagged doubles. (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 __ pextrd(Operand(edx), xmm1, 0x1); // copy xmm1[63..32] to edx.
2700 __ movd(Operand(ebx), xmm1);
2701
2702 // xmm1 = double value
2703 // ebx = low 32 bits of double value
2704 // edx = high 32 bits of double value
2705 // Compute hash (the shifts are arithmetic):
2706 // h = (low ^ high); h ^= h >> 16; h ^= h >> 8; h = h & (cacheSize - 1);
2707 __ mov(ecx, ebx);
2708 __ xor_(ecx, Operand(edx));
2709 __ mov(eax, ecx);
2710 __ sar(eax, 16);
2711 __ xor_(ecx, Operand(eax));
2712 __ mov(eax, ecx);
2713 __ sar(eax, 8);
2714 __ xor_(ecx, Operand(eax));
2715 ASSERT(IsPowerOf2(TranscendentalCache::kCacheSize));
2716 __ and_(Operand(ecx), Immediate(TranscendentalCache::kCacheSize - 1));
2717
2718 // xmm1 = double value.
2719 // ebx = low 32 bits of double value.
2720 // edx = high 32 bits of double value.
2721 // ecx = TranscendentalCache::hash(double value).
2722 __ mov(eax,
2723 Immediate(ExternalReference::transcendental_cache_array_address()));
2724 // Eax points to cache array.
2725 __ mov(eax, Operand(eax, type_ * sizeof(TranscendentalCache::caches_[0])));
2726 // Eax points to the cache for the type type_.
2727 // If NULL, the cache hasn't been initialized yet, so go through runtime.
2728 __ test(eax, Operand(eax));
2729 __ j(zero, &call_runtime);
2730 #ifdef DEBUG
2731 // Check that the layout of cache elements match expectations.
2732 { TranscendentalCache::Element test_elem[2];
2733 char* elem_start = reinterpret_cast<char*>(&test_elem[0]);
2734 char* elem2_start = reinterpret_cast<char*>(&test_elem[1]);
2735 char* elem_in0 = reinterpret_cast<char*>(&(test_elem[0].in[0]));
2736 char* elem_in1 = reinterpret_cast<char*>(&(test_elem[0].in[1]));
2737 char* elem_out = reinterpret_cast<char*>(&(test_elem[0].output));
2738 CHECK_EQ(12, elem2_start - elem_start); // Two uint_32's and a pointer.
2739 CHECK_EQ(0, elem_in0 - elem_start);
2740 CHECK_EQ(kIntSize, elem_in1 - elem_start);
2741 CHECK_EQ(2 * kIntSize, elem_out - elem_start);
2742 }
2743 #endif
2744 // Find the address of the ecx'th entry in the cache, i.e., &eax[ecx*12].
2745 __ lea(ecx, Operand(ecx, ecx, times_2, 0));
2746 __ lea(ecx, Operand(eax, ecx, times_4, 0));
2747 // Check if cache matches: Double value is stored in uint32_t[2] array.
2748 NearLabel cache_miss;
2749 __ cmp(ebx, Operand(ecx, 0));
2750 __ j(not_equal, &cache_miss);
2751 __ cmp(edx, Operand(ecx, kIntSize));
2752 __ j(not_equal, &cache_miss);
2753 // Cache hit!
2754 __ mov(eax, Operand(ecx, 2 * kIntSize));
2755 __ movdbl(xmm1, FieldOperand(eax, HeapNumber::kValueOffset));
2756 __ Ret();
2757
2758 __ bind(&cache_miss);
2759 // Update cache with new value.
2760 // We are short on registers, so use no_reg as scratch.
2761 // This gives slightly larger code.
2762 __ AllocateHeapNumber(eax, edi, no_reg, &skip_cache);
2763 __ sub(Operand(esp), Immediate(sizeof(double)));
2764 __ movdbl(Operand(esp, 0), xmm1);
2765 __ fld_d(Operand(esp, 0));
2766 __ add(Operand(esp), Immediate(sizeof(double)));
2767 GenerateOperation(masm);
2768 __ mov(Operand(ecx, 0), ebx);
2769 __ mov(Operand(ecx, kIntSize), edx);
2770 __ mov(Operand(ecx, 2 * kIntSize), eax);
2771 __ fstp_d(FieldOperand(eax, HeapNumber::kValueOffset));
2772 __ movdbl(xmm1, FieldOperand(eax, HeapNumber::kValueOffset));
2773 __ Ret();
2774
2775 __ bind(&skip_cache);
2776 __ sub(Operand(esp), Immediate(2 * kPointerSize));
2777 __ movdbl(Operand(esp, 0), xmm1);
2778 __ fld_d(Operand(esp, 0));
2779 GenerateOperation(masm);
2780 __ fstp_d(Operand(esp, 0));
2781 __ movdbl(xmm1, Operand(esp, 0));
2782 __ add(Operand(esp), Immediate(2 * kPointerSize));
2783 __ Ret();
2784
2785 __ bind(&call_runtime);
2786 __ AllocateHeapNumber(eax, edi, no_reg, &skip_cache);
2787 __ push(eax);
2788 __ movdbl(FieldOperand(eax, HeapNumber::kValueOffset), xmm1);
2789 __ CallRuntime(RuntimeFunction(), 1);
2790 __ movdbl(xmm1, FieldOperand(eax, HeapNumber::kValueOffset));
2791 __ Ret();
2792 }
2793
2794
2795 Runtime::FunctionId TranscendentalCacheSSE2Stub::RuntimeFunction() {
2796 switch (type_) {
2797 // Add more cases when necessary.
2798 case TranscendentalCache::LOG: return Runtime::kMath_log;
2799 default:
2800 UNIMPLEMENTED();
2801 return Runtime::kAbort;
2802 }
2803 }
2804
2805
2806 void TranscendentalCacheSSE2Stub::GenerateOperation(MacroAssembler* masm) {
2807 // Only free register is edi.
2808 // Input value is on FP stack and in xmm1.
2809
2810 ASSERT(type_ == TranscendentalCache::LOG);
2811 __ fldln2();
2812 __ fxch();
2813 __ fyl2x();
2814 }
2815
2816
2686 // Get the integer part of a heap number. Surprisingly, all this bit twiddling 2817 // 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. 2818 // 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 2819 // Trashes edi and ebx. Dest is ecx. Source cannot be ecx or one of the
2689 // trashed registers. 2820 // trashed registers.
2690 void IntegerConvert(MacroAssembler* masm, 2821 void IntegerConvert(MacroAssembler* masm,
2691 Register source, 2822 Register source,
2692 TypeInfo type_info, 2823 TypeInfo type_info,
2693 bool use_sse3, 2824 bool use_sse3,
2694 Label* conversion_failure) { 2825 Label* conversion_failure) {
2695 ASSERT(!source.is(ecx) && !source.is(edi) && !source.is(ebx)); 2826 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. 6414 // Do a tail call to the rewritten stub.
6284 __ jmp(Operand(edi)); 6415 __ jmp(Operand(edi));
6285 } 6416 }
6286 6417
6287 6418
6288 #undef __ 6419 #undef __
6289 6420
6290 } } // namespace v8::internal 6421 } } // namespace v8::internal
6291 6422
6292 #endif // V8_TARGET_ARCH_IA32 6423 #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