Index: src/objects.cc |
=================================================================== |
--- src/objects.cc (revision 3336) |
+++ src/objects.cc (working copy) |
@@ -37,6 +37,7 @@ |
#include "scanner.h" |
#include "scopeinfo.h" |
#include "string-stream.h" |
+#include "utils.h" |
#ifdef ENABLE_DISASSEMBLER |
#include "disassembler.h" |
@@ -754,19 +755,21 @@ |
ASSERT(size >= ExternalString::kSize); |
bool is_symbol = this->IsSymbol(); |
int length = this->length(); |
+ int hash_field = this->hash_field(); |
// Morph the object to an external string by adjusting the map and |
// reinitializing the fields. |
- this->set_map(ExternalTwoByteString::StringMap(length)); |
+ this->set_map(Heap::external_string_map()); |
ExternalTwoByteString* self = ExternalTwoByteString::cast(this); |
self->set_length(length); |
+ self->set_hash_field(hash_field); |
self->set_resource(resource); |
// Additionally make the object into an external symbol if the original string |
// was a symbol to start with. |
if (is_symbol) { |
self->Hash(); // Force regeneration of the hash value. |
// Now morph this external string into a external symbol. |
- self->set_map(ExternalTwoByteString::SymbolMap(length)); |
+ this->set_map(Heap::external_symbol_map()); |
} |
// Fill the remainder of the string with dead wood. |
@@ -798,19 +801,21 @@ |
ASSERT(size >= ExternalString::kSize); |
bool is_symbol = this->IsSymbol(); |
int length = this->length(); |
+ int hash_field = this->hash_field(); |
// Morph the object to an external string by adjusting the map and |
// reinitializing the fields. |
- this->set_map(ExternalAsciiString::StringMap(length)); |
+ this->set_map(Heap::external_ascii_string_map()); |
ExternalAsciiString* self = ExternalAsciiString::cast(this); |
self->set_length(length); |
+ self->set_hash_field(hash_field); |
self->set_resource(resource); |
// Additionally make the object into an external symbol if the original string |
// was a symbol to start with. |
if (is_symbol) { |
self->Hash(); // Force regeneration of the hash value. |
// Now morph this external string into a external symbol. |
- self->set_map(ExternalAsciiString::SymbolMap(length)); |
+ this->set_map(Heap::external_ascii_symbol_map()); |
} |
// Fill the remainder of the string with dead wood. |
@@ -822,7 +827,7 @@ |
void String::StringShortPrint(StringStream* accumulator) { |
int len = length(); |
- if (len > kMaxMediumSize) { |
+ if (len > kMaxShortPrintLength) { |
accumulator->Add("<Very long string[%u]>", len); |
return; |
} |
@@ -4484,24 +4489,12 @@ |
if (StringShape(this).IsSymbol()) return false; |
Map* map = this->map(); |
- if (map == Heap::short_string_map()) { |
- this->set_map(Heap::undetectable_short_string_map()); |
+ if (map == Heap::string_map()) { |
+ this->set_map(Heap::undetectable_string_map()); |
return true; |
- } else if (map == Heap::medium_string_map()) { |
- this->set_map(Heap::undetectable_medium_string_map()); |
+ } else if (map == Heap::ascii_string_map()) { |
+ this->set_map(Heap::undetectable_ascii_string_map()); |
return true; |
- } else if (map == Heap::long_string_map()) { |
- this->set_map(Heap::undetectable_long_string_map()); |
- return true; |
- } else if (map == Heap::short_ascii_string_map()) { |
- this->set_map(Heap::undetectable_short_ascii_string_map()); |
- return true; |
- } else if (map == Heap::medium_ascii_string_map()) { |
- this->set_map(Heap::undetectable_medium_ascii_string_map()); |
- return true; |
- } else if (map == Heap::long_ascii_string_map()) { |
- this->set_map(Heap::undetectable_long_ascii_string_map()); |
- return true; |
} |
// Rest cannot be marked as undetectable |
return false; |
@@ -4523,17 +4516,17 @@ |
uint32_t String::ComputeAndSetHash() { |
// Should only be called if hash code has not yet been computed. |
- ASSERT(!(length_field() & kHashComputedMask)); |
+ ASSERT(!(hash_field() & kHashComputedMask)); |
// Compute the hash code. |
StringInputBuffer buffer(this); |
- uint32_t field = ComputeLengthAndHashField(&buffer, length()); |
+ uint32_t field = ComputeHashField(&buffer, length()); |
// Store the hash code in the object. |
- set_length_field(field); |
+ set_hash_field(field); |
// Check the hash code is there. |
- ASSERT(length_field() & kHashComputedMask); |
+ ASSERT(hash_field() & kHashComputedMask); |
uint32_t result = field >> kHashShift; |
ASSERT(result != 0); // Ensure that the hash value of 0 is never computed. |
return result; |
@@ -4573,9 +4566,10 @@ |
bool String::SlowAsArrayIndex(uint32_t* index) { |
if (length() <= kMaxCachedArrayIndexLength) { |
Hash(); // force computation of hash code |
- uint32_t field = length_field(); |
+ uint32_t field = hash_field(); |
if ((field & kIsArrayIndexMask) == 0) return false; |
- *index = (field & ((1 << kShortLengthShift) - 1)) >> kLongLengthShift; |
+ // Isolate the array index form the full hash field. |
+ *index = (kArrayIndexHashMask & field) >> kHashShift; |
return true; |
} else { |
StringInputBuffer buffer(this); |
@@ -4584,37 +4578,42 @@ |
} |
-static inline uint32_t HashField(uint32_t hash, bool is_array_index) { |
+static inline uint32_t HashField(uint32_t hash, |
+ bool is_array_index, |
+ int length = -1) { |
uint32_t result = |
- (hash << String::kLongLengthShift) | String::kHashComputedMask; |
- if (is_array_index) result |= String::kIsArrayIndexMask; |
+ (hash << String::kHashShift) | String::kHashComputedMask; |
+ if (is_array_index) { |
+ // For array indexes mix the length into the hash as an array index could |
+ // be zero. |
+ ASSERT(length > 0); |
+ ASSERT(TenToThe(String::kMaxCachedArrayIndexLength) < |
+ (1 << String::kArrayIndexValueBits)); |
+ result |= String::kIsArrayIndexMask; |
+ result |= length << String::kArrayIndexHashLengthShift; |
+ } |
return result; |
} |
uint32_t StringHasher::GetHashField() { |
ASSERT(is_valid()); |
- if (length_ <= String::kMaxShortSize) { |
- uint32_t payload; |
+ if (length_ <= String::kMaxHashCalcLength) { |
if (is_array_index()) { |
- payload = v8::internal::HashField(array_index(), true); |
+ return v8::internal::HashField(array_index(), true, length_); |
} else { |
- payload = v8::internal::HashField(GetHash(), false); |
+ return v8::internal::HashField(GetHash(), false); |
} |
- return (payload & ((1 << String::kShortLengthShift) - 1)) | |
- (length_ << String::kShortLengthShift); |
- } else if (length_ <= String::kMaxMediumSize) { |
uint32_t payload = v8::internal::HashField(GetHash(), false); |
- return (payload & ((1 << String::kMediumLengthShift) - 1)) | |
- (length_ << String::kMediumLengthShift); |
+ return payload; |
} else { |
return v8::internal::HashField(length_, false); |
} |
} |
-uint32_t String::ComputeLengthAndHashField(unibrow::CharacterStream* buffer, |
- int length) { |
+uint32_t String::ComputeHashField(unibrow::CharacterStream* buffer, |
+ int length) { |
StringHasher hasher(length); |
// Very long strings have a trivial hash that doesn't inspect the |
@@ -6177,6 +6176,7 @@ |
return pt->GetPropertyWithReceiver(receiver, name, attributes); |
} |
+ |
Object* JSObject::GetLocalPropertyPostInterceptor( |
JSObject* receiver, |
String* name, |
@@ -6737,19 +6737,19 @@ |
class Utf8SymbolKey : public HashTableKey { |
public: |
explicit Utf8SymbolKey(Vector<const char> string) |
- : string_(string), length_field_(0) { } |
+ : string_(string), hash_field_(0) { } |
bool IsMatch(Object* string) { |
return String::cast(string)->IsEqualTo(string_); |
} |
uint32_t Hash() { |
- if (length_field_ != 0) return length_field_ >> String::kHashShift; |
+ if (hash_field_ != 0) return hash_field_ >> String::kHashShift; |
unibrow::Utf8InputBuffer<> buffer(string_.start(), |
static_cast<unsigned>(string_.length())); |
chars_ = buffer.Length(); |
- length_field_ = String::ComputeLengthAndHashField(&buffer, chars_); |
- uint32_t result = length_field_ >> String::kHashShift; |
+ hash_field_ = String::ComputeHashField(&buffer, chars_); |
+ uint32_t result = hash_field_ >> String::kHashShift; |
ASSERT(result != 0); // Ensure that the hash value of 0 is never computed. |
return result; |
} |
@@ -6759,12 +6759,12 @@ |
} |
Object* AsObject() { |
- if (length_field_ == 0) Hash(); |
- return Heap::AllocateSymbol(string_, chars_, length_field_); |
+ if (hash_field_ == 0) Hash(); |
+ return Heap::AllocateSymbol(string_, chars_, hash_field_); |
} |
Vector<const char> string_; |
- uint32_t length_field_; |
+ uint32_t hash_field_; |
int chars_; // Caches the number of characters when computing the hash code. |
}; |
@@ -6805,7 +6805,7 @@ |
StringInputBuffer buffer(string_); |
return Heap::AllocateInternalSymbol(&buffer, |
string_->length(), |
- string_->length_field()); |
+ string_->hash_field()); |
} |
static uint32_t StringHash(Object* obj) { |