Index: src/heap.h |
=================================================================== |
--- src/heap.h (revision 2785) |
+++ src/heap.h (working copy) |
@@ -28,8 +28,11 @@ |
#ifndef V8_HEAP_H_ |
#define V8_HEAP_H_ |
+#include <math.h> |
+ |
#include "zone-inl.h" |
+ |
namespace v8 { |
namespace internal { |
@@ -1519,6 +1522,89 @@ |
int previous_marked_count_; |
}; |
+ |
+class TranscendentalCache { |
+ public: |
+ enum Type {ACOS, ASIN, ATAN, COS, EXP, LOG, SIN, TAN, kNumberOfCaches}; |
+ |
+ TranscendentalCache(Type t); |
+ |
+ static inline Object* Get(Type type, double input) { |
Søren Thygesen Gjesse
2009/09/01 08:40:31
Please add a (short) comment on this public Get fu
|
+ TranscendentalCache* cache = caches_[type]; |
Søren Thygesen Gjesse
2009/09/01 08:40:31
The description says "Cache the results of slow ma
Erik Corry
2009/09/01 09:02:28
The cache only works in the runtime system. If we
|
+ if (cache == NULL) { |
+ caches_[type] = cache = new TranscendentalCache(type); |
+ } |
+ return cache->Get(input); |
+ } |
+ |
+ // The cache contains raw Object pointers. This method disposes of |
+ // them before a garbage collection. |
+ static void Clear(); |
+ |
+ private: |
+ inline Object* Get(double input) { |
+ Converter c; |
+ c.dbl = input; |
+ int hash = Hash(c); |
+ Element e = elements_[hash]; |
+ if (e.in[0] == c.integers[0] && |
+ e.in[1] == c.integers[1]) { |
+ ASSERT(e.output != NULL); |
+ return e.output; |
+ } |
+ double answer = Calculate(input); |
+ Object* heap_number = Heap::AllocateHeapNumber(answer); |
+ if (!heap_number->IsFailure()) { |
+ elements_[hash].in[0] = c.integers[0]; |
+ elements_[hash].in[1] = c.integers[1]; |
+ elements_[hash].output = heap_number; |
+ } |
+ return heap_number; |
+ } |
+ |
+ inline double Calculate(double input) { |
+ switch(type_) { |
+ case ACOS: |
+ return acos(input); |
+ case ASIN: |
+ return asin(input); |
+ case ATAN: |
+ return atan(input); |
+ case COS: |
+ return cos(input); |
+ case EXP: |
+ return exp(input); |
+ case LOG: |
+ return log(input); |
+ case SIN: |
+ return sin(input); |
+ case TAN: |
+ return tan(input); |
+ default: |
+ return 0.0; // Never happens. |
+ } |
+ } |
+ static const int kCacheSize = 512; |
+ struct Element { |
+ uint32_t in[2]; |
+ Object* output; |
+ }; |
+ union Converter { |
+ double dbl; |
+ uint32_t integers[2]; |
+ }; |
+ inline static int Hash(const Converter& c) { |
+ uint32_t hash = (c.integers[0] ^ c.integers[1]); |
+ hash ^= hash >> 16; |
+ hash ^= hash >> 8; |
+ return (hash & (kCacheSize - 1)); |
+ } |
+ static TranscendentalCache* caches_[kNumberOfCaches]; |
+ Element elements_[kCacheSize]; |
+ Type type_; |
+}; |
+ |
+ |
} } // namespace v8::internal |
#endif // V8_HEAP_H_ |