/src/mozilla-central/dom/media/webaudio/blink/DenormalDisabler.h
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | * Copyright (C) 2011, Google Inc. All rights reserved. |
3 | | * |
4 | | * Redistribution and use in source and binary forms, with or without |
5 | | * modification, are permitted provided that the following conditions |
6 | | * are met: |
7 | | * 1. Redistributions of source code must retain the above copyright |
8 | | * notice, this list of conditions and the following disclaimer. |
9 | | * 2. Redistributions in binary form must reproduce the above copyright |
10 | | * notice, this list of conditions and the following disclaimer in the |
11 | | * documentation and/or other materials provided with the distribution. |
12 | | * |
13 | | * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY |
14 | | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
15 | | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
16 | | * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY |
17 | | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
18 | | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
19 | | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON |
20 | | * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
21 | | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
22 | | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
23 | | */ |
24 | | |
25 | | #ifndef DenormalDisabler_h |
26 | | #define DenormalDisabler_h |
27 | | |
28 | | #include <cmath> |
29 | | #include <float.h> |
30 | | |
31 | | namespace WebCore { |
32 | | |
33 | | // Deal with denormals. They can very seriously impact performance on x86. |
34 | | |
35 | | // Define HAVE_DENORMAL if we support flushing denormals to zero. |
36 | | |
37 | | #if defined (XP_WIN) && defined(_MSC_VER) |
38 | | // Windows compiled using MSVC with SSE2 |
39 | | #define HAVE_DENORMAL 1 |
40 | | #endif |
41 | | |
42 | | #if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__)) |
43 | | // X86 chips can flush denormals |
44 | | #define HAVE_DENORMAL 1 |
45 | | #endif |
46 | | |
47 | | #if defined(__arm__) || defined(__aarch64__) |
48 | | #define HAVE_DENORMAL 1 |
49 | | #endif |
50 | | |
51 | | #ifdef HAVE_DENORMAL |
52 | | class DenormalDisabler { |
53 | | public: |
54 | | DenormalDisabler() |
55 | | : m_savedCSR(0) |
56 | 0 | { |
57 | 0 | disableDenormals(); |
58 | 0 | } |
59 | | |
60 | | ~DenormalDisabler() |
61 | 0 | { |
62 | 0 | restoreState(); |
63 | 0 | } |
64 | | |
65 | | // This is a nop if we can flush denormals to zero in hardware. |
66 | | static inline float flushDenormalFloatToZero(float f) |
67 | 0 | { |
68 | 0 | return f; |
69 | 0 | } |
70 | | private: |
71 | | unsigned m_savedCSR; |
72 | | |
73 | | #if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__)) |
74 | | inline void disableDenormals() |
75 | 0 | { |
76 | 0 | m_savedCSR = getCSR(); |
77 | 0 | setCSR(m_savedCSR | 0x8040); |
78 | 0 | } |
79 | | |
80 | | inline void restoreState() |
81 | 0 | { |
82 | 0 | setCSR(m_savedCSR); |
83 | 0 | } |
84 | | |
85 | | inline int getCSR() |
86 | 0 | { |
87 | 0 | int result; |
88 | 0 | asm volatile("stmxcsr %0" : "=m" (result)); |
89 | 0 | return result; |
90 | 0 | } |
91 | | |
92 | | inline void setCSR(int a) |
93 | 0 | { |
94 | 0 | int temp = a; |
95 | 0 | asm volatile("ldmxcsr %0" : : "m" (temp)); |
96 | 0 | } |
97 | | |
98 | | #elif defined (XP_WIN) && defined(_MSC_VER) |
99 | | inline void disableDenormals() |
100 | | { |
101 | | // Save the current state, and set mode to flush denormals. |
102 | | // |
103 | | // http://stackoverflow.com/questions/637175/possible-bug-in-controlfp-s-may-not-restore-control-word-correctly |
104 | | _controlfp_s(&m_savedCSR, 0, 0); |
105 | | unsigned unused; |
106 | | _controlfp_s(&unused, _DN_FLUSH, _MCW_DN); |
107 | | } |
108 | | |
109 | | inline void restoreState() |
110 | | { |
111 | | unsigned unused; |
112 | | _controlfp_s(&unused, m_savedCSR, _MCW_DN); |
113 | | } |
114 | | #elif defined(__arm__) || defined(__aarch64__) |
115 | | inline void disableDenormals() |
116 | | { |
117 | | m_savedCSR = getStatusWord(); |
118 | | // Bit 24 is the flush-to-zero mode control bit. Setting it to 1 flushes denormals to 0. |
119 | | setStatusWord(m_savedCSR | (1 << 24)); |
120 | | } |
121 | | |
122 | | inline void restoreState() |
123 | | { |
124 | | setStatusWord(m_savedCSR); |
125 | | } |
126 | | |
127 | | inline int getStatusWord() |
128 | | { |
129 | | int result; |
130 | | #if defined(__aarch64__) |
131 | | asm volatile("mrs %x[result], FPCR" : [result] "=r" (result)); |
132 | | #else |
133 | | asm volatile("vmrs %[result], FPSCR" : [result] "=r" (result)); |
134 | | #endif |
135 | | return result; |
136 | | } |
137 | | |
138 | | inline void setStatusWord(int a) |
139 | | { |
140 | | #if defined(__aarch64__) |
141 | | asm volatile("msr FPCR, %x[src]" : : [src] "r" (a)); |
142 | | #else |
143 | | asm volatile("vmsr FPSCR, %[src]" : : [src] "r" (a)); |
144 | | #endif |
145 | | } |
146 | | |
147 | | #endif |
148 | | |
149 | | }; |
150 | | |
151 | | #else |
152 | | // FIXME: add implementations for other architectures and compilers |
153 | | class DenormalDisabler { |
154 | | public: |
155 | | DenormalDisabler() { } |
156 | | |
157 | | // Assume the worst case that other architectures and compilers |
158 | | // need to flush denormals to zero manually. |
159 | | static inline float flushDenormalFloatToZero(float f) |
160 | | { |
161 | | return (fabs(f) < FLT_MIN) ? 0.0f : f; |
162 | | } |
163 | | }; |
164 | | |
165 | | #endif |
166 | | |
167 | | } // namespace WebCore |
168 | | #endif // DenormalDisabler_h |