From 0575396a4cf1bed8ffe6727b447fc53f5bc60909 Mon Sep 17 00:00:00 2001 From: "ulan@chromium.org" Date: Fri, 17 Jan 2014 10:27:57 +0000 Subject: [PATCH] Refactor string internalization. Remove duplicate code in StringTable and Heap. Instead of having many InternalizeXXXString methods, add a general InternalizeStringWithKey that takes a string table key. BUG= R=dcarney@chromium.org, svenpanne@chromium.org Review URL: https://codereview.chromium.org/140953002 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@18657 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- src/factory.cc | 25 ++++---- src/factory.h | 3 + src/heap.cc | 77 ++++++------------------ src/heap.h | 9 +-- src/objects-inl.h | 128 ++++++++++++++++++++++++++++++++++++++- src/objects.cc | 176 ++++-------------------------------------------------- src/objects.h | 17 +----- 7 files changed, 178 insertions(+), 257 deletions(-) diff --git a/src/factory.cc b/src/factory.cc index 2b5cf8b..65888ac 100644 --- a/src/factory.cc +++ b/src/factory.cc @@ -206,9 +206,8 @@ Handle Factory::NewTypeFeedbackInfo() { // Internalized strings are created in the old generation (data space). Handle Factory::InternalizeUtf8String(Vector string) { - CALL_HEAP_FUNCTION(isolate(), - isolate()->heap()->InternalizeUtf8String(string), - String); + Utf8StringKey key(string, isolate()->heap()->HashSeed()); + return InternalizeStringWithKey(&key); } @@ -221,24 +220,28 @@ Handle Factory::InternalizeString(Handle string) { Handle Factory::InternalizeOneByteString(Vector string) { - CALL_HEAP_FUNCTION(isolate(), - isolate()->heap()->InternalizeOneByteString(string), - String); + OneByteStringKey key(string, isolate()->heap()->HashSeed()); + return InternalizeStringWithKey(&key); } Handle Factory::InternalizeOneByteString( Handle string, int from, int length) { - CALL_HEAP_FUNCTION(isolate(), - isolate()->heap()->InternalizeOneByteString( - string, from, length), - String); + SubStringOneByteStringKey key(string, from, length); + return InternalizeStringWithKey(&key); } Handle Factory::InternalizeTwoByteString(Vector string) { + TwoByteStringKey key(string, isolate()->heap()->HashSeed()); + return InternalizeStringWithKey(&key); +} + + +template +Handle Factory::InternalizeStringWithKey(StringTableKey* key) { CALL_HEAP_FUNCTION(isolate(), - isolate()->heap()->InternalizeTwoByteString(string), + isolate()->heap()->InternalizeStringWithKey(key), String); } diff --git a/src/factory.h b/src/factory.h index 8753bd8..8ca9d48 100644 --- a/src/factory.h +++ b/src/factory.h @@ -104,6 +104,9 @@ class Factory { int length); Handle InternalizeTwoByteString(Vector str); + template + Handle InternalizeStringWithKey(StringTableKey* key); + // String creation functions. Most of the string creation functions take // a Heap::PretenureFlag argument to optionally request that they be diff --git a/src/heap.cc b/src/heap.cc index 5e3d759..5c6eb18 100644 --- a/src/heap.cc +++ b/src/heap.cc @@ -3858,8 +3858,8 @@ MaybeObject* Heap::LookupSingleCharacterStringFromCode(uint16_t code) { uint8_t buffer[1]; buffer[0] = static_cast(code); Object* result; - MaybeObject* maybe_result = - InternalizeOneByteString(Vector(buffer, 1)); + OneByteStringKey key(Vector(buffer, 1), HashSeed()); + MaybeObject* maybe_result = InternalizeStringWithKey(&key); if (!maybe_result->ToObject(&result)) return maybe_result; single_character_string_cache()->set(code, result); @@ -4742,8 +4742,9 @@ MaybeObject* Heap::ReinitializeJSReceiver( SharedFunctionInfo* shared = NULL; if (type == JS_FUNCTION_TYPE) { String* name; - maybe = - InternalizeOneByteString(STATIC_ASCII_VECTOR("")); + OneByteStringKey key(STATIC_ASCII_VECTOR(""), + HashSeed()); + maybe = InternalizeStringWithKey(&key); if (!maybe->To(&name)) return maybe; maybe = AllocateSharedFunctionInfo(name); if (!maybe->To(&shared)) return maybe; @@ -5876,45 +5877,17 @@ void Heap::Verify() { MaybeObject* Heap::InternalizeUtf8String(Vector string) { - Object* result = NULL; - Object* new_table; - { MaybeObject* maybe_new_table = - string_table()->LookupUtf8String(string, &result); - if (!maybe_new_table->ToObject(&new_table)) return maybe_new_table; - } - // Can't use set_string_table because StringTable::cast knows that - // StringTable is a singleton and checks for identity. - roots_[kStringTableRootIndex] = new_table; - ASSERT(result != NULL); - return result; -} - - -MaybeObject* Heap::InternalizeOneByteString(Vector string) { - Object* result = NULL; - Object* new_table; - { MaybeObject* maybe_new_table = - string_table()->LookupOneByteString(string, &result); - if (!maybe_new_table->ToObject(&new_table)) return maybe_new_table; - } - // Can't use set_string_table because StringTable::cast knows that - // StringTable is a singleton and checks for identity. - roots_[kStringTableRootIndex] = new_table; - ASSERT(result != NULL); - return result; + Utf8StringKey key(string, HashSeed()); + return InternalizeStringWithKey(&key); } -MaybeObject* Heap::InternalizeOneByteString(Handle string, - int from, - int length) { +MaybeObject* Heap::InternalizeString(String* string) { + if (string->IsInternalizedString()) return string; Object* result = NULL; Object* new_table; { MaybeObject* maybe_new_table = - string_table()->LookupSubStringOneByteString(string, - from, - length, - &result); + string_table()->LookupString(string, &result); if (!maybe_new_table->ToObject(&new_table)) return maybe_new_table; } // Can't use set_string_table because StringTable::cast knows that @@ -5925,27 +5898,20 @@ MaybeObject* Heap::InternalizeOneByteString(Handle string, } -MaybeObject* Heap::InternalizeTwoByteString(Vector string) { - Object* result = NULL; - Object* new_table; - { MaybeObject* maybe_new_table = - string_table()->LookupTwoByteString(string, &result); - if (!maybe_new_table->ToObject(&new_table)) return maybe_new_table; +bool Heap::InternalizeStringIfExists(String* string, String** result) { + if (string->IsInternalizedString()) { + *result = string; + return true; } - // Can't use set_string_table because StringTable::cast knows that - // StringTable is a singleton and checks for identity. - roots_[kStringTableRootIndex] = new_table; - ASSERT(result != NULL); - return result; + return string_table()->LookupStringIfExists(string, result); } -MaybeObject* Heap::InternalizeString(String* string) { - if (string->IsInternalizedString()) return string; +MaybeObject* Heap::InternalizeStringWithKey(HashTableKey* key) { Object* result = NULL; Object* new_table; { MaybeObject* maybe_new_table = - string_table()->LookupString(string, &result); + string_table()->LookupKey(key, &result); if (!maybe_new_table->ToObject(&new_table)) return maybe_new_table; } // Can't use set_string_table because StringTable::cast knows that @@ -5956,15 +5922,6 @@ MaybeObject* Heap::InternalizeString(String* string) { } -bool Heap::InternalizeStringIfExists(String* string, String** result) { - if (string->IsInternalizedString()) { - *result = string; - return true; - } - return string_table()->LookupStringIfExists(string, result); -} - - void Heap::ZapFromSpace() { NewSpacePageIterator it(new_space_.FromSpaceStart(), new_space_.FromSpaceEnd()); diff --git a/src/heap.h b/src/heap.h index 0847298..49c536b 100644 --- a/src/heap.h +++ b/src/heap.h @@ -1143,16 +1143,13 @@ class Heap { // Returns Failure::RetryAfterGC(requested_bytes, space) if allocation // failed. // Please note this function does not perform a garbage collection. - MUST_USE_RESULT MaybeObject* InternalizeUtf8String(Vector str); MUST_USE_RESULT MaybeObject* InternalizeUtf8String(const char* str) { return InternalizeUtf8String(CStrVector(str)); } - MUST_USE_RESULT MaybeObject* InternalizeOneByteString( - Vector str); - MUST_USE_RESULT MaybeObject* InternalizeTwoByteString(Vector str); + MUST_USE_RESULT MaybeObject* InternalizeUtf8String(Vector str); + MUST_USE_RESULT MaybeObject* InternalizeString(String* str); - MUST_USE_RESULT MaybeObject* InternalizeOneByteString( - Handle string, int from, int length); + MUST_USE_RESULT MaybeObject* InternalizeStringWithKey(HashTableKey* key); bool InternalizeStringIfExists(String* str, String** result); bool InternalizeTwoCharsStringIfExists(String* str, String** result); diff --git a/src/objects-inl.h b/src/objects-inl.h index 7bd8d59..fb996a2 100644 --- a/src/objects-inl.h +++ b/src/objects-inl.h @@ -459,6 +459,133 @@ uc32 FlatStringReader::Get(int index) { } +template +class SequentialStringKey : public HashTableKey { + public: + explicit SequentialStringKey(Vector string, uint32_t seed) + : string_(string), hash_field_(0), seed_(seed) { } + + virtual uint32_t Hash() { + hash_field_ = StringHasher::HashSequentialString(string_.start(), + string_.length(), + seed_); + + uint32_t result = hash_field_ >> String::kHashShift; + ASSERT(result != 0); // Ensure that the hash value of 0 is never computed. + return result; + } + + + virtual uint32_t HashForObject(Object* other) { + return String::cast(other)->Hash(); + } + + Vector string_; + uint32_t hash_field_; + uint32_t seed_; +}; + + +class OneByteStringKey : public SequentialStringKey { + public: + OneByteStringKey(Vector str, uint32_t seed) + : SequentialStringKey(str, seed) { } + + virtual bool IsMatch(Object* string) { + return String::cast(string)->IsOneByteEqualTo(string_); + } + + virtual MaybeObject* AsObject(Heap* heap); +}; + + +class SubStringOneByteStringKey : public HashTableKey { + public: + explicit SubStringOneByteStringKey(Handle string, + int from, + int length) + : string_(string), from_(from), length_(length) { } + + virtual uint32_t Hash() { + ASSERT(length_ >= 0); + ASSERT(from_ + length_ <= string_->length()); + uint8_t* chars = string_->GetChars() + from_; + hash_field_ = StringHasher::HashSequentialString( + chars, length_, string_->GetHeap()->HashSeed()); + uint32_t result = hash_field_ >> String::kHashShift; + ASSERT(result != 0); // Ensure that the hash value of 0 is never computed. + return result; + } + + + virtual uint32_t HashForObject(Object* other) { + return String::cast(other)->Hash(); + } + + virtual bool IsMatch(Object* string) { + Vector chars(string_->GetChars() + from_, length_); + return String::cast(string)->IsOneByteEqualTo(chars); + } + + virtual MaybeObject* AsObject(Heap* heap); + + private: + Handle string_; + int from_; + int length_; + uint32_t hash_field_; +}; + + +class TwoByteStringKey : public SequentialStringKey { + public: + explicit TwoByteStringKey(Vector str, uint32_t seed) + : SequentialStringKey(str, seed) { } + + virtual bool IsMatch(Object* string) { + return String::cast(string)->IsTwoByteEqualTo(string_); + } + + virtual MaybeObject* AsObject(Heap* heap); +}; + + +// Utf8StringKey carries a vector of chars as key. +class Utf8StringKey : public HashTableKey { + public: + explicit Utf8StringKey(Vector string, uint32_t seed) + : string_(string), hash_field_(0), seed_(seed) { } + + virtual bool IsMatch(Object* string) { + return String::cast(string)->IsUtf8EqualTo(string_); + } + + virtual uint32_t Hash() { + if (hash_field_ != 0) return hash_field_ >> String::kHashShift; + hash_field_ = StringHasher::ComputeUtf8Hash(string_, seed_, &chars_); + uint32_t result = hash_field_ >> String::kHashShift; + ASSERT(result != 0); // Ensure that the hash value of 0 is never computed. + return result; + } + + virtual uint32_t HashForObject(Object* other) { + return String::cast(other)->Hash(); + } + + virtual MaybeObject* AsObject(Heap* heap) { + if (hash_field_ == 0) Hash(); + return heap->AllocateInternalizedStringFromUtf8(string_, + chars_, + hash_field_); + } + + Vector string_; + uint32_t hash_field_; + int chars_; // Caches the number of characters when computing the hash code. + uint32_t seed_; +}; + + bool Object::IsNumber() { return IsSmi() || IsHeapNumber(); } @@ -6671,7 +6798,6 @@ void FlexibleBodyDescriptor::IterateBody(HeapObject* obj, #undef READ_BYTE_FIELD #undef WRITE_BYTE_FIELD - } } // namespace v8::internal #endif // V8_OBJECTS_INL_H_ diff --git a/src/objects.cc b/src/objects.cc index 18a811b..e476324 100644 --- a/src/objects.cc +++ b/src/objects.cc @@ -14000,142 +14000,23 @@ class RegExpKey : public HashTableKey { }; -// Utf8StringKey carries a vector of chars as key. -class Utf8StringKey : public HashTableKey { - public: - explicit Utf8StringKey(Vector string, uint32_t seed) - : string_(string), hash_field_(0), seed_(seed) { } - - bool IsMatch(Object* string) { - return String::cast(string)->IsUtf8EqualTo(string_); - } - - uint32_t Hash() { - if (hash_field_ != 0) return hash_field_ >> String::kHashShift; - hash_field_ = StringHasher::ComputeUtf8Hash(string_, seed_, &chars_); - uint32_t result = hash_field_ >> String::kHashShift; - ASSERT(result != 0); // Ensure that the hash value of 0 is never computed. - return result; - } - - uint32_t HashForObject(Object* other) { - return String::cast(other)->Hash(); - } - - MaybeObject* AsObject(Heap* heap) { - if (hash_field_ == 0) Hash(); - return heap->AllocateInternalizedStringFromUtf8(string_, - chars_, - hash_field_); - } - - Vector string_; - uint32_t hash_field_; - int chars_; // Caches the number of characters when computing the hash code. - uint32_t seed_; -}; - - -template -class SequentialStringKey : public HashTableKey { - public: - explicit SequentialStringKey(Vector string, uint32_t seed) - : string_(string), hash_field_(0), seed_(seed) { } - - uint32_t Hash() { - hash_field_ = StringHasher::HashSequentialString(string_.start(), - string_.length(), - seed_); - - uint32_t result = hash_field_ >> String::kHashShift; - ASSERT(result != 0); // Ensure that the hash value of 0 is never computed. - return result; - } - - - uint32_t HashForObject(Object* other) { - return String::cast(other)->Hash(); - } - - Vector string_; - uint32_t hash_field_; - uint32_t seed_; -}; - - - -class OneByteStringKey : public SequentialStringKey { - public: - OneByteStringKey(Vector str, uint32_t seed) - : SequentialStringKey(str, seed) { } - - bool IsMatch(Object* string) { - return String::cast(string)->IsOneByteEqualTo(string_); - } - - MaybeObject* AsObject(Heap* heap) { - if (hash_field_ == 0) Hash(); - return heap->AllocateOneByteInternalizedString(string_, hash_field_); - } -}; - - -class SubStringOneByteStringKey : public HashTableKey { - public: - explicit SubStringOneByteStringKey(Handle string, - int from, - int length) - : string_(string), from_(from), length_(length) { } - - uint32_t Hash() { - ASSERT(length_ >= 0); - ASSERT(from_ + length_ <= string_->length()); - uint8_t* chars = string_->GetChars() + from_; - hash_field_ = StringHasher::HashSequentialString( - chars, length_, string_->GetHeap()->HashSeed()); - uint32_t result = hash_field_ >> String::kHashShift; - ASSERT(result != 0); // Ensure that the hash value of 0 is never computed. - return result; - } - - - uint32_t HashForObject(Object* other) { - return String::cast(other)->Hash(); - } - - bool IsMatch(Object* string) { - Vector chars(string_->GetChars() + from_, length_); - return String::cast(string)->IsOneByteEqualTo(chars); - } +MaybeObject* OneByteStringKey::AsObject(Heap* heap) { + if (hash_field_ == 0) Hash(); + return heap->AllocateOneByteInternalizedString(string_, hash_field_); +} - MaybeObject* AsObject(Heap* heap) { - if (hash_field_ == 0) Hash(); - Vector chars(string_->GetChars() + from_, length_); - return heap->AllocateOneByteInternalizedString(chars, hash_field_); - } - - private: - Handle string_; - int from_; - int length_; - uint32_t hash_field_; -}; +MaybeObject* SubStringOneByteStringKey::AsObject(Heap* heap) { + if (hash_field_ == 0) Hash(); + Vector chars(string_->GetChars() + from_, length_); + return heap->AllocateOneByteInternalizedString(chars, hash_field_); +} -class TwoByteStringKey : public SequentialStringKey { - public: - explicit TwoByteStringKey(Vector str, uint32_t seed) - : SequentialStringKey(str, seed) { } - bool IsMatch(Object* string) { - return String::cast(string)->IsTwoByteEqualTo(string_); - } - - MaybeObject* AsObject(Heap* heap) { - if (hash_field_ == 0) Hash(); - return heap->AllocateTwoByteInternalizedString(string_, hash_field_); - } -}; +MaybeObject* TwoByteStringKey::AsObject(Heap* heap) { + if (hash_field_ == 0) Hash(); + return heap->AllocateTwoByteInternalizedString(string_, hash_field_); +} // InternalizedStringKey carries a string/internalized-string object as key. @@ -15199,37 +15080,6 @@ bool StringTable::LookupTwoCharsStringIfExists(uint16_t c1, } -MaybeObject* StringTable::LookupUtf8String(Vector str, - Object** s) { - Utf8StringKey key(str, GetHeap()->HashSeed()); - return LookupKey(&key, s); -} - - -MaybeObject* StringTable::LookupOneByteString(Vector str, - Object** s) { - OneByteStringKey key(str, GetHeap()->HashSeed()); - return LookupKey(&key, s); -} - - -MaybeObject* StringTable::LookupSubStringOneByteString( - Handle str, - int from, - int length, - Object** s) { - SubStringOneByteStringKey key(str, from, length); - return LookupKey(&key, s); -} - - -MaybeObject* StringTable::LookupTwoByteString(Vector str, - Object** s) { - TwoByteStringKey key(str, GetHeap()->HashSeed()); - return LookupKey(&key, s); -} - - MaybeObject* StringTable::LookupKey(HashTableKey* key, Object** s) { int entry = FindEntry(key); diff --git a/src/objects.h b/src/objects.h index 7d036eb..dd0bb1e 100644 --- a/src/objects.h +++ b/src/objects.h @@ -3767,21 +3767,8 @@ class StringTable: public HashTable { // added. The return value is the string table which might have // been enlarged. If the return value is not a failure, the string // pointer *s is set to the string found. - MUST_USE_RESULT MaybeObject* LookupUtf8String( - Vector str, - Object** s); - MUST_USE_RESULT MaybeObject* LookupOneByteString( - Vector str, - Object** s); - MUST_USE_RESULT MaybeObject* LookupSubStringOneByteString( - Handle str, - int from, - int length, - Object** s); - MUST_USE_RESULT MaybeObject* LookupTwoByteString( - Vector str, - Object** s); MUST_USE_RESULT MaybeObject* LookupString(String* key, Object** s); + MUST_USE_RESULT MaybeObject* LookupKey(HashTableKey* key, Object** s); // Looks up a string that is equal to the given string and returns // true if it is found, assigning the string to the given output @@ -3793,8 +3780,6 @@ class StringTable: public HashTable { static inline StringTable* cast(Object* obj); private: - MUST_USE_RESULT MaybeObject* LookupKey(HashTableKey* key, Object** s); - template friend class JsonParser; DISALLOW_IMPLICIT_CONSTRUCTORS(StringTable); -- 2.7.4