1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/content/media/webaudio/blink/DenormalDisabler.h Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,125 @@ 1.4 +/* 1.5 + * Copyright (C) 2011, Google Inc. All rights reserved. 1.6 + * 1.7 + * Redistribution and use in source and binary forms, with or without 1.8 + * modification, are permitted provided that the following conditions 1.9 + * are met: 1.10 + * 1. Redistributions of source code must retain the above copyright 1.11 + * notice, this list of conditions and the following disclaimer. 1.12 + * 2. Redistributions in binary form must reproduce the above copyright 1.13 + * notice, this list of conditions and the following disclaimer in the 1.14 + * documentation and/or other materials provided with the distribution. 1.15 + * 1.16 + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY 1.17 + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 1.18 + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 1.19 + * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY 1.20 + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 1.21 + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 1.22 + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 1.23 + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 1.24 + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 1.25 + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 1.26 + */ 1.27 + 1.28 +#ifndef DenormalDisabler_h 1.29 +#define DenormalDisabler_h 1.30 + 1.31 +#define _USE_MATH_DEFINES 1.32 +#include <cmath> 1.33 +#include <float.h> 1.34 + 1.35 +namespace WebCore { 1.36 + 1.37 +// Deal with denormals. They can very seriously impact performance on x86. 1.38 + 1.39 +// Define HAVE_DENORMAL if we support flushing denormals to zero. 1.40 +#if defined(XP_WIN) && defined(_MSC_VER) 1.41 +#define HAVE_DENORMAL 1.42 +#endif 1.43 + 1.44 +#if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__)) 1.45 +#define HAVE_DENORMAL 1.46 +#endif 1.47 + 1.48 +#ifdef HAVE_DENORMAL 1.49 +class DenormalDisabler { 1.50 +public: 1.51 + DenormalDisabler() 1.52 + : m_savedCSR(0) 1.53 + { 1.54 +#if defined(XP_WIN) && defined(_MSC_VER) 1.55 + // Save the current state, and set mode to flush denormals. 1.56 + // 1.57 + // http://stackoverflow.com/questions/637175/possible-bug-in-controlfp-s-may-not-restore-control-word-correctly 1.58 + _controlfp_s(&m_savedCSR, 0, 0); 1.59 + unsigned int unused; 1.60 + _controlfp_s(&unused, _DN_FLUSH, _MCW_DN); 1.61 +#else 1.62 + m_savedCSR = getCSR(); 1.63 + setCSR(m_savedCSR | 0x8040); 1.64 +#endif 1.65 + } 1.66 + 1.67 + ~DenormalDisabler() 1.68 + { 1.69 +#if defined(XP_WIN) && defined(_MSC_VER) 1.70 + unsigned int unused; 1.71 + _controlfp_s(&unused, m_savedCSR, _MCW_DN); 1.72 +#else 1.73 + setCSR(m_savedCSR); 1.74 +#endif 1.75 + } 1.76 + 1.77 + // This is a nop if we can flush denormals to zero in hardware. 1.78 + static inline float flushDenormalFloatToZero(float f) 1.79 + { 1.80 +#if defined(XP_WIN) && defined(_MSC_VER) && _M_IX86_FP 1.81 + // For systems using x87 instead of sse, there's no hardware support 1.82 + // to flush denormals automatically. Hence, we need to flush 1.83 + // denormals to zero manually. 1.84 + return (fabs(f) < FLT_MIN) ? 0.0f : f; 1.85 +#else 1.86 + return f; 1.87 +#endif 1.88 + } 1.89 +private: 1.90 +#if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__)) 1.91 + inline int getCSR() 1.92 + { 1.93 + int result; 1.94 + asm volatile("stmxcsr %0" : "=m" (result)); 1.95 + return result; 1.96 + } 1.97 + 1.98 + inline void setCSR(int a) 1.99 + { 1.100 + int temp = a; 1.101 + asm volatile("ldmxcsr %0" : : "m" (temp)); 1.102 + } 1.103 + 1.104 +#endif 1.105 + 1.106 + unsigned int m_savedCSR; 1.107 +}; 1.108 + 1.109 +#else 1.110 +// FIXME: add implementations for other architectures and compilers 1.111 +class DenormalDisabler { 1.112 +public: 1.113 + DenormalDisabler() { } 1.114 + 1.115 + // Assume the worst case that other architectures and compilers 1.116 + // need to flush denormals to zero manually. 1.117 + static inline float flushDenormalFloatToZero(float f) 1.118 + { 1.119 + return (fabs(f) < FLT_MIN) ? 0.0f : f; 1.120 + } 1.121 +}; 1.122 + 1.123 +#endif 1.124 + 1.125 +} // WebCore 1.126 + 1.127 +#undef HAVE_DENORMAL 1.128 +#endif // DenormalDisabler_h