121939df44de1705786c545cd1bf519d47250322dBen Murdoch/*
221939df44de1705786c545cd1bf519d47250322dBen Murdoch * Copyright (C) 2010 Apple Inc. All rights reserved.
321939df44de1705786c545cd1bf519d47250322dBen Murdoch *
421939df44de1705786c545cd1bf519d47250322dBen Murdoch * Redistribution and use in source and binary forms, with or without
521939df44de1705786c545cd1bf519d47250322dBen Murdoch * modification, are permitted provided that the following conditions
621939df44de1705786c545cd1bf519d47250322dBen Murdoch * are met:
721939df44de1705786c545cd1bf519d47250322dBen Murdoch * 1. Redistributions of source code must retain the above copyright
821939df44de1705786c545cd1bf519d47250322dBen Murdoch *    notice, this list of conditions and the following disclaimer.
921939df44de1705786c545cd1bf519d47250322dBen Murdoch * 2. Redistributions in binary form must reproduce the above copyright
1021939df44de1705786c545cd1bf519d47250322dBen Murdoch *    notice, this list of conditions and the following disclaimer in the
1121939df44de1705786c545cd1bf519d47250322dBen Murdoch *    documentation and/or other materials provided with the distribution.
1221939df44de1705786c545cd1bf519d47250322dBen Murdoch *
1321939df44de1705786c545cd1bf519d47250322dBen Murdoch * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
1421939df44de1705786c545cd1bf519d47250322dBen Murdoch * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1521939df44de1705786c545cd1bf519d47250322dBen Murdoch * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
1621939df44de1705786c545cd1bf519d47250322dBen Murdoch * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
1721939df44de1705786c545cd1bf519d47250322dBen Murdoch * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
1821939df44de1705786c545cd1bf519d47250322dBen Murdoch * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
1921939df44de1705786c545cd1bf519d47250322dBen Murdoch * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
2021939df44de1705786c545cd1bf519d47250322dBen Murdoch * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
2121939df44de1705786c545cd1bf519d47250322dBen Murdoch * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2221939df44de1705786c545cd1bf519d47250322dBen Murdoch * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
2321939df44de1705786c545cd1bf519d47250322dBen Murdoch * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2421939df44de1705786c545cd1bf519d47250322dBen Murdoch */
2521939df44de1705786c545cd1bf519d47250322dBen Murdoch
2621939df44de1705786c545cd1bf519d47250322dBen Murdoch#ifndef CachedTranscendentalFunction_h
2721939df44de1705786c545cd1bf519d47250322dBen Murdoch#define CachedTranscendentalFunction_h
2821939df44de1705786c545cd1bf519d47250322dBen Murdoch
2921939df44de1705786c545cd1bf519d47250322dBen Murdoch#include "JSValue.h"
3021939df44de1705786c545cd1bf519d47250322dBen Murdoch
3121939df44de1705786c545cd1bf519d47250322dBen Murdochnamespace JSC {
3221939df44de1705786c545cd1bf519d47250322dBen Murdoch
3321939df44de1705786c545cd1bf519d47250322dBen Murdochextern const double NaN;
3421939df44de1705786c545cd1bf519d47250322dBen Murdoch
3521939df44de1705786c545cd1bf519d47250322dBen Murdochtypedef double (*TranscendentalFunctionPtr)(double);
3621939df44de1705786c545cd1bf519d47250322dBen Murdoch
3721939df44de1705786c545cd1bf519d47250322dBen Murdoch// CachedTranscendentalFunction provides a generic mechanism to cache results
3821939df44de1705786c545cd1bf519d47250322dBen Murdoch// for pure functions with the signature "double func(double)", and where NaN
3921939df44de1705786c545cd1bf519d47250322dBen Murdoch// maps to NaN.
4021939df44de1705786c545cd1bf519d47250322dBen Murdochtemplate<TranscendentalFunctionPtr orignalFunction>
4121939df44de1705786c545cd1bf519d47250322dBen Murdochclass CachedTranscendentalFunction {
4221939df44de1705786c545cd1bf519d47250322dBen Murdoch    struct CacheEntry {
4321939df44de1705786c545cd1bf519d47250322dBen Murdoch        double operand;
4421939df44de1705786c545cd1bf519d47250322dBen Murdoch        double result;
4521939df44de1705786c545cd1bf519d47250322dBen Murdoch    };
4621939df44de1705786c545cd1bf519d47250322dBen Murdoch
4721939df44de1705786c545cd1bf519d47250322dBen Murdochpublic:
4821939df44de1705786c545cd1bf519d47250322dBen Murdoch    CachedTranscendentalFunction()
4921939df44de1705786c545cd1bf519d47250322dBen Murdoch        : m_cache(0)
5021939df44de1705786c545cd1bf519d47250322dBen Murdoch    {
5121939df44de1705786c545cd1bf519d47250322dBen Murdoch    }
5221939df44de1705786c545cd1bf519d47250322dBen Murdoch
5321939df44de1705786c545cd1bf519d47250322dBen Murdoch    ~CachedTranscendentalFunction()
5421939df44de1705786c545cd1bf519d47250322dBen Murdoch    {
5521939df44de1705786c545cd1bf519d47250322dBen Murdoch        if (m_cache)
5621939df44de1705786c545cd1bf519d47250322dBen Murdoch            fastFree(m_cache);
5721939df44de1705786c545cd1bf519d47250322dBen Murdoch    }
5821939df44de1705786c545cd1bf519d47250322dBen Murdoch
59e14391e94c850b8bd03680c23b38978db68687a8John Reck    JSValue operator() (double operand)
6021939df44de1705786c545cd1bf519d47250322dBen Murdoch    {
6121939df44de1705786c545cd1bf519d47250322dBen Murdoch        if (UNLIKELY(!m_cache))
6221939df44de1705786c545cd1bf519d47250322dBen Murdoch            initialize();
6321939df44de1705786c545cd1bf519d47250322dBen Murdoch        CacheEntry* entry = &m_cache[hash(operand)];
6421939df44de1705786c545cd1bf519d47250322dBen Murdoch
6521939df44de1705786c545cd1bf519d47250322dBen Murdoch        if (entry->operand == operand)
66e14391e94c850b8bd03680c23b38978db68687a8John Reck            return jsDoubleNumber(entry->result);
6721939df44de1705786c545cd1bf519d47250322dBen Murdoch        double result = orignalFunction(operand);
6821939df44de1705786c545cd1bf519d47250322dBen Murdoch        entry->operand = operand;
6921939df44de1705786c545cd1bf519d47250322dBen Murdoch        entry->result = result;
70e14391e94c850b8bd03680c23b38978db68687a8John Reck        return jsDoubleNumber(result);
7121939df44de1705786c545cd1bf519d47250322dBen Murdoch    }
7221939df44de1705786c545cd1bf519d47250322dBen Murdoch
7321939df44de1705786c545cd1bf519d47250322dBen Murdochprivate:
7421939df44de1705786c545cd1bf519d47250322dBen Murdoch    void initialize()
7521939df44de1705786c545cd1bf519d47250322dBen Murdoch    {
7621939df44de1705786c545cd1bf519d47250322dBen Murdoch        // Lazily allocate the table, populate with NaN->NaN mapping.
7721939df44de1705786c545cd1bf519d47250322dBen Murdoch        m_cache = static_cast<CacheEntry*>(fastMalloc(s_cacheSize * sizeof(CacheEntry)));
7821939df44de1705786c545cd1bf519d47250322dBen Murdoch        for (unsigned x = 0; x < s_cacheSize; ++x) {
7921939df44de1705786c545cd1bf519d47250322dBen Murdoch            m_cache[x].operand = NaN;
8021939df44de1705786c545cd1bf519d47250322dBen Murdoch            m_cache[x].result = NaN;
8121939df44de1705786c545cd1bf519d47250322dBen Murdoch        }
8221939df44de1705786c545cd1bf519d47250322dBen Murdoch    }
8321939df44de1705786c545cd1bf519d47250322dBen Murdoch
8421939df44de1705786c545cd1bf519d47250322dBen Murdoch    static unsigned hash(double d)
8521939df44de1705786c545cd1bf519d47250322dBen Murdoch    {
8621939df44de1705786c545cd1bf519d47250322dBen Murdoch        union doubleAndUInt64 {
8721939df44de1705786c545cd1bf519d47250322dBen Murdoch            double d;
8821939df44de1705786c545cd1bf519d47250322dBen Murdoch            uint32_t is[2];
8921939df44de1705786c545cd1bf519d47250322dBen Murdoch        } u;
9021939df44de1705786c545cd1bf519d47250322dBen Murdoch        u.d = d;
9121939df44de1705786c545cd1bf519d47250322dBen Murdoch
9221939df44de1705786c545cd1bf519d47250322dBen Murdoch        unsigned x = u.is[0] ^ u.is[1];
9321939df44de1705786c545cd1bf519d47250322dBen Murdoch        x = (x >> 20) ^ (x >> 8);
9421939df44de1705786c545cd1bf519d47250322dBen Murdoch        return x & (s_cacheSize - 1);
9521939df44de1705786c545cd1bf519d47250322dBen Murdoch    }
9621939df44de1705786c545cd1bf519d47250322dBen Murdoch
9721939df44de1705786c545cd1bf519d47250322dBen Murdoch    static const unsigned s_cacheSize = 0x1000;
9821939df44de1705786c545cd1bf519d47250322dBen Murdoch    CacheEntry* m_cache;
9921939df44de1705786c545cd1bf519d47250322dBen Murdoch};
10021939df44de1705786c545cd1bf519d47250322dBen Murdoch
10121939df44de1705786c545cd1bf519d47250322dBen Murdoch}
10221939df44de1705786c545cd1bf519d47250322dBen Murdoch
10321939df44de1705786c545cd1bf519d47250322dBen Murdoch#endif // CachedTranscendentalFunction_h
104