OLD | NEW |
1 // Copyright 2006-2008 the V8 project authors. All rights reserved. | 1 // Copyright 2006-2008 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 3755 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3766 return i == slen && !decoder->has_more(); | 3766 return i == slen && !decoder->has_more(); |
3767 } | 3767 } |
3768 | 3768 |
3769 | 3769 |
3770 uint32_t String::ComputeAndSetHash() { | 3770 uint32_t String::ComputeAndSetHash() { |
3771 // Should only be call if hash code has not yet been computed. | 3771 // Should only be call if hash code has not yet been computed. |
3772 ASSERT(!(length_field() & kHashComputedMask)); | 3772 ASSERT(!(length_field() & kHashComputedMask)); |
3773 | 3773 |
3774 // Compute the hash code. | 3774 // Compute the hash code. |
3775 StringInputBuffer buffer(this); | 3775 StringInputBuffer buffer(this); |
3776 int hash = ComputeHashCode(&buffer, length()); | 3776 uint32_t field = ComputeLengthAndHashField(&buffer, length()); |
3777 | 3777 |
3778 // Store the hash code in the object. | 3778 // Store the hash code in the object. |
3779 set_length_field(hash); | 3779 set_length_field(field); |
3780 | 3780 |
3781 // Check the hash code is there. | 3781 // Check the hash code is there. |
3782 ASSERT(length_field() & kHashComputedMask); | 3782 ASSERT(length_field() & kHashComputedMask); |
3783 return hash; | 3783 return field >> kHashShift; |
3784 } | 3784 } |
3785 | 3785 |
3786 | 3786 |
3787 bool String::ComputeArrayIndex(unibrow::CharacterStream* buffer, | 3787 bool String::ComputeArrayIndex(unibrow::CharacterStream* buffer, |
3788 uint32_t* index, | 3788 uint32_t* index, |
3789 int length) { | 3789 int length) { |
3790 if (length == 0) return false; | 3790 if (length == 0) return false; |
3791 uc32 ch = buffer->GetNext(); | 3791 uc32 ch = buffer->GetNext(); |
3792 | 3792 |
3793 // If the string begins with a '0' character, it must only consist | 3793 // If the string begins with a '0' character, it must only consist |
(...skipping 24 matching lines...) Expand all Loading... |
3818 StringInputBuffer buffer(this); | 3818 StringInputBuffer buffer(this); |
3819 return ComputeArrayIndex(&buffer, index, length()); | 3819 return ComputeArrayIndex(&buffer, index, length()); |
3820 } | 3820 } |
3821 | 3821 |
3822 | 3822 |
3823 static inline uint32_t HashField(uint32_t hash, bool is_array_index) { | 3823 static inline uint32_t HashField(uint32_t hash, bool is_array_index) { |
3824 return (hash << String::kLongLengthShift) | (is_array_index ? 3 : 1); | 3824 return (hash << String::kLongLengthShift) | (is_array_index ? 3 : 1); |
3825 } | 3825 } |
3826 | 3826 |
3827 | 3827 |
3828 uint32_t String::ComputeHashCode(unibrow::CharacterStream* buffer, | 3828 uint32_t String::ComputeLengthAndHashField(unibrow::CharacterStream* buffer, |
3829 int length) { | 3829 int length) { |
3830 // Large string (please note large strings cannot be an array index). | 3830 // Large string (please note large strings cannot be an array index). |
3831 if (length > kMaxMediumStringSize) return HashField(length, false); | 3831 if (length > kMaxMediumStringSize) return HashField(length, false); |
3832 | 3832 |
3833 // Note: the Jenkins one-at-a-time hash function | 3833 // Note: the Jenkins one-at-a-time hash function |
3834 uint32_t hash = 0; | 3834 uint32_t hash = 0; |
3835 while (buffer->has_more()) { | 3835 while (buffer->has_more()) { |
3836 uc32 r = buffer->GetNext(); | 3836 uc32 r = buffer->GetNext(); |
3837 hash += r; | 3837 hash += r; |
3838 hash += (hash << 10); | 3838 hash += (hash << 10); |
3839 hash ^= (hash >> 6); | 3839 hash ^= (hash >> 6); |
(...skipping 1583 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5423 | 5423 |
5424 bool IsStringKey() { return true; } | 5424 bool IsStringKey() { return true; } |
5425 | 5425 |
5426 String* string_; | 5426 String* string_; |
5427 }; | 5427 }; |
5428 | 5428 |
5429 // Utf8SymbolKey carries a vector of chars as key. | 5429 // Utf8SymbolKey carries a vector of chars as key. |
5430 class Utf8SymbolKey : public HashTableKey { | 5430 class Utf8SymbolKey : public HashTableKey { |
5431 public: | 5431 public: |
5432 explicit Utf8SymbolKey(Vector<const char> string) | 5432 explicit Utf8SymbolKey(Vector<const char> string) |
5433 : string_(string), hash_(0) { } | 5433 : string_(string), length_field_(0) { } |
5434 | 5434 |
5435 bool IsMatch(Object* other) { | 5435 bool IsMatch(Object* other) { |
5436 if (!other->IsString()) return false; | 5436 if (!other->IsString()) return false; |
5437 return String::cast(other)->IsEqualTo(string_); | 5437 return String::cast(other)->IsEqualTo(string_); |
5438 } | 5438 } |
5439 | 5439 |
5440 HashFunction GetHashFunction() { | 5440 HashFunction GetHashFunction() { |
5441 return StringHash; | 5441 return StringHash; |
5442 } | 5442 } |
5443 | 5443 |
5444 uint32_t Hash() { | 5444 uint32_t Hash() { |
5445 if (hash_ != 0) return hash_; | 5445 if (length_field_ != 0) return length_field_ >> String::kHashShift; |
5446 unibrow::Utf8InputBuffer<> buffer(string_.start(), | 5446 unibrow::Utf8InputBuffer<> buffer(string_.start(), |
5447 static_cast<unsigned>(string_.length())); | 5447 static_cast<unsigned>(string_.length())); |
5448 chars_ = buffer.Length(); | 5448 chars_ = buffer.Length(); |
5449 hash_ = String::ComputeHashCode(&buffer, chars_); | 5449 length_field_ = String::ComputeLengthAndHashField(&buffer, chars_); |
5450 return hash_; | 5450 return length_field_ >> String::kHashShift; |
5451 } | 5451 } |
5452 | 5452 |
5453 Object* GetObject() { | 5453 Object* GetObject() { |
5454 if (hash_ == 0) Hash(); | 5454 if (length_field_ == 0) Hash(); |
5455 unibrow::Utf8InputBuffer<> buffer(string_.start(), | 5455 unibrow::Utf8InputBuffer<> buffer(string_.start(), |
5456 static_cast<unsigned>(string_.length())); | 5456 static_cast<unsigned>(string_.length())); |
5457 return Heap::AllocateSymbol(&buffer, chars_, hash_); | 5457 return Heap::AllocateSymbol(&buffer, chars_, length_field_); |
5458 } | 5458 } |
5459 | 5459 |
5460 static uint32_t StringHash(Object* obj) { | 5460 static uint32_t StringHash(Object* obj) { |
5461 return String::cast(obj)->Hash(); | 5461 return String::cast(obj)->Hash(); |
5462 } | 5462 } |
5463 | 5463 |
5464 bool IsStringKey() { return true; } | 5464 bool IsStringKey() { return true; } |
5465 | 5465 |
5466 Vector<const char> string_; | 5466 Vector<const char> string_; |
5467 uint32_t hash_; | 5467 uint32_t length_field_; |
5468 int chars_; // Caches the number of characters when computing the hash code. | 5468 int chars_; // Caches the number of characters when computing the hash code. |
5469 }; | 5469 }; |
5470 | 5470 |
5471 | 5471 |
5472 // SymbolKey carries a string/symbol object as key. | 5472 // SymbolKey carries a string/symbol object as key. |
5473 class SymbolKey : public HashTableKey { | 5473 class SymbolKey : public HashTableKey { |
5474 public: | 5474 public: |
5475 explicit SymbolKey(String* string) : string_(string) { } | 5475 explicit SymbolKey(String* string) : string_(string) { } |
5476 | 5476 |
5477 HashFunction GetHashFunction() { | 5477 HashFunction GetHashFunction() { |
(...skipping 18 matching lines...) Expand all Loading... |
5496 } | 5496 } |
5497 } | 5497 } |
5498 // Transform string to symbol if possible. | 5498 // Transform string to symbol if possible. |
5499 Map* map = Heap::SymbolMapForString(string_); | 5499 Map* map = Heap::SymbolMapForString(string_); |
5500 if (map != NULL) { | 5500 if (map != NULL) { |
5501 string_->set_map(map); | 5501 string_->set_map(map); |
5502 return string_; | 5502 return string_; |
5503 } | 5503 } |
5504 // Otherwise allocate a new symbol. | 5504 // Otherwise allocate a new symbol. |
5505 StringInputBuffer buffer(string_); | 5505 StringInputBuffer buffer(string_); |
5506 return Heap::AllocateSymbol(&buffer, string_->length(), string_->Hash()); | 5506 return Heap::AllocateSymbol(&buffer, |
| 5507 string_->length(), |
| 5508 string_->length_field()); |
5507 } | 5509 } |
5508 | 5510 |
5509 static uint32_t StringHash(Object* obj) { | 5511 static uint32_t StringHash(Object* obj) { |
5510 return String::cast(obj)->Hash(); | 5512 return String::cast(obj)->Hash(); |
5511 } | 5513 } |
5512 | 5514 |
5513 bool IsStringKey() { return true; } | 5515 bool IsStringKey() { return true; } |
5514 | 5516 |
5515 String* string_; | 5517 String* string_; |
5516 }; | 5518 }; |
(...skipping 910 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6427 // No break point. | 6429 // No break point. |
6428 if (break_point_objects()->IsUndefined()) return 0; | 6430 if (break_point_objects()->IsUndefined()) return 0; |
6429 // Single beak point. | 6431 // Single beak point. |
6430 if (!break_point_objects()->IsFixedArray()) return 1; | 6432 if (!break_point_objects()->IsFixedArray()) return 1; |
6431 // Multiple break points. | 6433 // Multiple break points. |
6432 return FixedArray::cast(break_point_objects())->length(); | 6434 return FixedArray::cast(break_point_objects())->length(); |
6433 } | 6435 } |
6434 | 6436 |
6435 | 6437 |
6436 } } // namespace v8::internal | 6438 } } // namespace v8::internal |
OLD | NEW |