Chromium Code Reviews| Index: src/objects.cc |
| =================================================================== |
| --- src/objects.cc (revision 1344) |
| +++ src/objects.cc (working copy) |
| @@ -5850,6 +5850,20 @@ |
| } |
| +// Thomas Wang, Integer Hash Functions. |
| +// http://www.concentric.net/~Ttwang/tech/inthash.htm |
| +static uint32_t ComputeIntegerHash(uint32_t key) { |
| + uint32_t hash = key; |
| + hash = ~hash + (hash << 15); // hash = (hash << 15) - hash - 1; |
| + hash = hash ^ (hash >> 12); |
| + hash = hash + (hash << 2); |
| + hash = hash ^ (hash >> 4); |
| + hash = hash * 2057; // hash = (hash + (hash << 3)) + (hash << 11); |
| + hash = hash ^ (hash >> 16); |
| + return hash; |
| +} |
| + |
| + |
| // The NumberKey uses carries the uint32_t as key. |
| // This avoids allocation in HasProperty. |
| class NumberKey : public HashTableKey { |
| @@ -5861,21 +5875,8 @@ |
| return number_ == ToUint32(number); |
| } |
| - // Thomas Wang, Integer Hash Functions. |
| - // http://www.concentric.net/~Ttwang/tech/inthash.htm |
| - static uint32_t ComputeHash(uint32_t key) { |
| - uint32_t hash = key; |
| - hash = ~hash + (hash << 15); // hash = (hash << 15) - hash - 1; |
| - hash = hash ^ (hash >> 12); |
| - hash = hash + (hash << 2); |
| - hash = hash ^ (hash >> 4); |
| - hash = hash * 2057; // hash = (hash + (hash << 3)) + (hash << 11); |
| - hash = hash ^ (hash >> 16); |
| - return hash; |
| - } |
| + uint32_t Hash() { return ComputeIntegerHash(number_); } |
| - uint32_t Hash() { return ComputeHash(number_); } |
| - |
| HashFunction GetHashFunction() { return NumberHash; } |
| Object* GetObject() { |
| @@ -5883,7 +5884,7 @@ |
| } |
| static uint32_t NumberHash(Object* obj) { |
| - return ComputeHash(ToUint32(obj)); |
| + return ComputeIntegerHash(ToUint32(obj)); |
| } |
| static uint32_t ToUint32(Object* obj) { |
| @@ -5921,6 +5922,70 @@ |
| String* string_; |
| }; |
| + |
| +// StringSharedKeys are used as keys in the eval cache. |
| +class StringSharedKey : public HashTableKey { |
| + public: |
| + StringSharedKey(String* source, SharedFunctionInfo* shared) |
| + : source_(source), shared_(shared) { } |
| + |
| + bool IsMatch(Object* other) { |
| + if (!other->IsFixedArray()) return false; |
| + FixedArray* pair = FixedArray::cast(other); |
| + SharedFunctionInfo* shared = SharedFunctionInfo::cast(pair->get(0)); |
| + if (shared != shared_) return false; |
| + String* source = String::cast(pair->get(1)); |
| + return source->Equals(source_); |
| + } |
| + |
| + typedef uint32_t (*HashFunction)(Object* obj); |
| + |
| + virtual HashFunction GetHashFunction() { return StringSharedHash; } |
| + |
| + static uint32_t StringSharedHashHelper(String* source, |
| + SharedFunctionInfo* shared) { |
| + uint32_t hash = source->Hash(); |
| + if (shared->HasSourceCode()) { |
| + // Instead of using the SharedFunctionInfo pointer in the hash |
| + // code computation, we use a combination of the hash of the |
| + // script source code and the start and end positions. We do |
| + // this to ensure that the cache entries can survive garbage |
| + // collection. |
| + Script* script = Script::cast(shared->script()); |
| + hash ^= String::cast(script->source())->Hash(); |
|
Kasper Lund
2009/02/24 11:21:08
It's not clear that this is a great way of mixing
|
| + hash ^= ((shared->start_position() << 16) | shared->end_position()); |
| + } |
| + return hash; |
| + } |
| + |
| + static uint32_t StringSharedHash(Object* obj) { |
| + FixedArray* pair = FixedArray::cast(obj); |
| + SharedFunctionInfo* shared = SharedFunctionInfo::cast(pair->get(0)); |
| + String* source = String::cast(pair->get(1)); |
| + return StringSharedHashHelper(source, shared); |
| + } |
| + |
| + virtual uint32_t Hash() { |
| + return StringSharedHashHelper(source_, shared_); |
| + } |
| + |
| + virtual Object* GetObject() { |
| + Object* obj = Heap::AllocateFixedArray(2); |
| + if (obj->IsFailure()) return obj; |
| + FixedArray* pair = FixedArray::cast(obj); |
| + pair->set(0, shared_); |
| + pair->set(1, source_); |
| + return pair; |
| + } |
| + |
| + virtual bool IsStringKey() { return false; } |
| + |
| + private: |
| + String* source_; |
| + SharedFunctionInfo* shared_; |
| +}; |
| + |
| + |
| // RegExpKey carries the source and flags of a regular expression as key. |
| class RegExpKey : public HashTableKey { |
| public: |
| @@ -6234,6 +6299,14 @@ |
| } |
| +Object* CompilationCacheTable::LookupEval(String* src, Context* context) { |
| + StringSharedKey key(src, context->closure()->shared()); |
| + int entry = FindEntry(&key); |
| + if (entry == -1) return Heap::undefined_value(); |
| + return get(EntryToIndex(entry) + 1); |
| +} |
| + |
| + |
| Object* CompilationCacheTable::LookupRegExp(String* src, |
| JSRegExp::Flags flags) { |
| RegExpKey key(src, flags); |
| @@ -6258,6 +6331,27 @@ |
| } |
| +Object* CompilationCacheTable::PutEval(String* src, |
| + Context* context, |
| + Object* value) { |
| + StringSharedKey key(src, context->closure()->shared()); |
| + Object* obj = EnsureCapacity(1, &key); |
| + if (obj->IsFailure()) return obj; |
| + |
| + CompilationCacheTable* cache = |
| + reinterpret_cast<CompilationCacheTable*>(obj); |
| + int entry = cache->FindInsertionEntry(src, key.Hash()); |
| + |
| + Object* k = key.GetObject(); |
| + if (k->IsFailure()) return k; |
| + |
| + cache->set(EntryToIndex(entry), k); |
| + cache->set(EntryToIndex(entry) + 1, value); |
| + cache->ElementAdded(); |
| + return cache; |
| +} |
| + |
| + |
| Object* CompilationCacheTable::PutRegExp(String* src, |
| JSRegExp::Flags flags, |
| FixedArray* value) { |