1 /* 2 * Copyright (C) 2010 Apple 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. ``AS IS'' AND ANY 14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR 17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 */ 25 26 #ifndef CachedTranscendentalFunction_h 27 #define CachedTranscendentalFunction_h 28 29 #include "JSValue.h" 30 31 namespace JSC { 32 33 extern const double NaN; 34 35 typedef double (*TranscendentalFunctionPtr)(double); 36 37 // CachedTranscendentalFunction provides a generic mechanism to cache results 38 // for pure functions with the signature "double func(double)", and where NaN 39 // maps to NaN. 40 template<TranscendentalFunctionPtr orignalFunction> 41 class CachedTranscendentalFunction { 42 struct CacheEntry { 43 double operand; 44 double result; 45 }; 46 47 public: CachedTranscendentalFunction()48 CachedTranscendentalFunction() 49 : m_cache(0) 50 { 51 } 52 ~CachedTranscendentalFunction()53 ~CachedTranscendentalFunction() 54 { 55 if (m_cache) 56 fastFree(m_cache); 57 } 58 operator()59 JSValue operator() (double operand) 60 { 61 if (UNLIKELY(!m_cache)) 62 initialize(); 63 CacheEntry* entry = &m_cache[hash(operand)]; 64 65 if (entry->operand == operand) 66 return jsDoubleNumber(entry->result); 67 double result = orignalFunction(operand); 68 entry->operand = operand; 69 entry->result = result; 70 return jsDoubleNumber(result); 71 } 72 73 private: initialize()74 void initialize() 75 { 76 // Lazily allocate the table, populate with NaN->NaN mapping. 77 m_cache = static_cast<CacheEntry*>(fastMalloc(s_cacheSize * sizeof(CacheEntry))); 78 for (unsigned x = 0; x < s_cacheSize; ++x) { 79 m_cache[x].operand = NaN; 80 m_cache[x].result = NaN; 81 } 82 } 83 hash(double d)84 static unsigned hash(double d) 85 { 86 union doubleAndUInt64 { 87 double d; 88 uint32_t is[2]; 89 } u; 90 u.d = d; 91 92 unsigned x = u.is[0] ^ u.is[1]; 93 x = (x >> 20) ^ (x >> 8); 94 return x & (s_cacheSize - 1); 95 } 96 97 static const unsigned s_cacheSize = 0x1000; 98 CacheEntry* m_cache; 99 }; 100 101 } 102 103 #endif // CachedTranscendentalFunction_h 104