| 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) {
|
|
|