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
This commit is contained in:
ulan@chromium.org 2014-01-17 10:27:57 +00:00
parent 3a954aa52d
commit 0575396a4c
7 changed files with 183 additions and 262 deletions

View File

@ -206,9 +206,8 @@ Handle<TypeFeedbackInfo> Factory::NewTypeFeedbackInfo() {
// Internalized strings are created in the old generation (data space).
Handle<String> Factory::InternalizeUtf8String(Vector<const char> string) {
CALL_HEAP_FUNCTION(isolate(),
isolate()->heap()->InternalizeUtf8String(string),
String);
Utf8StringKey key(string, isolate()->heap()->HashSeed());
return InternalizeStringWithKey(&key);
}
@ -221,24 +220,28 @@ Handle<String> Factory::InternalizeString(Handle<String> string) {
Handle<String> Factory::InternalizeOneByteString(Vector<const uint8_t> string) {
CALL_HEAP_FUNCTION(isolate(),
isolate()->heap()->InternalizeOneByteString(string),
String);
OneByteStringKey key(string, isolate()->heap()->HashSeed());
return InternalizeStringWithKey(&key);
}
Handle<String> Factory::InternalizeOneByteString(
Handle<SeqOneByteString> 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<String> Factory::InternalizeTwoByteString(Vector<const uc16> string) {
TwoByteStringKey key(string, isolate()->heap()->HashSeed());
return InternalizeStringWithKey(&key);
}
template<class StringTableKey>
Handle<String> Factory::InternalizeStringWithKey(StringTableKey* key) {
CALL_HEAP_FUNCTION(isolate(),
isolate()->heap()->InternalizeTwoByteString(string),
isolate()->heap()->InternalizeStringWithKey(key),
String);
}

View File

@ -104,6 +104,9 @@ class Factory {
int length);
Handle<String> InternalizeTwoByteString(Vector<const uc16> str);
template<class StringTableKey>
Handle<String> InternalizeStringWithKey(StringTableKey* key);
// String creation functions. Most of the string creation functions take
// a Heap::PretenureFlag argument to optionally request that they be

View File

@ -3858,8 +3858,8 @@ MaybeObject* Heap::LookupSingleCharacterStringFromCode(uint16_t code) {
uint8_t buffer[1];
buffer[0] = static_cast<uint8_t>(code);
Object* result;
MaybeObject* maybe_result =
InternalizeOneByteString(Vector<const uint8_t>(buffer, 1));
OneByteStringKey key(Vector<const uint8_t>(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("<freezing call trap>"));
OneByteStringKey key(STATIC_ASCII_VECTOR("<freezing call trap>"),
HashSeed());
maybe = InternalizeStringWithKey(&key);
if (!maybe->To<String>(&name)) return maybe;
maybe = AllocateSharedFunctionInfo(name);
if (!maybe->To<SharedFunctionInfo>(&shared)) return maybe;
@ -5876,67 +5877,8 @@ void Heap::Verify() {
MaybeObject* Heap::InternalizeUtf8String(Vector<const char> 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<const uint8_t> 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;
}
MaybeObject* Heap::InternalizeOneByteString(Handle<SeqOneByteString> string,
int from,
int length) {
Object* result = NULL;
Object* new_table;
{ MaybeObject* maybe_new_table =
string_table()->LookupSubStringOneByteString(string,
from,
length,
&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::InternalizeTwoByteString(Vector<const uc16> 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;
}
// 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);
}
@ -5965,6 +5907,21 @@ bool Heap::InternalizeStringIfExists(String* string, String** result) {
}
MaybeObject* Heap::InternalizeStringWithKey(HashTableKey* key) {
Object* result = NULL;
Object* new_table;
{ MaybeObject* maybe_new_table =
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
// StringTable is a singleton and checks for identity.
roots_[kStringTableRootIndex] = new_table;
ASSERT(result != NULL);
return result;
}
void Heap::ZapFromSpace() {
NewSpacePageIterator it(new_space_.FromSpaceStart(),
new_space_.FromSpaceEnd());

View File

@ -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<const char> str);
MUST_USE_RESULT MaybeObject* InternalizeUtf8String(const char* str) {
return InternalizeUtf8String(CStrVector(str));
}
MUST_USE_RESULT MaybeObject* InternalizeOneByteString(
Vector<const uint8_t> str);
MUST_USE_RESULT MaybeObject* InternalizeTwoByteString(Vector<const uc16> str);
MUST_USE_RESULT MaybeObject* InternalizeUtf8String(Vector<const char> str);
MUST_USE_RESULT MaybeObject* InternalizeString(String* str);
MUST_USE_RESULT MaybeObject* InternalizeOneByteString(
Handle<SeqOneByteString> string, int from, int length);
MUST_USE_RESULT MaybeObject* InternalizeStringWithKey(HashTableKey* key);
bool InternalizeStringIfExists(String* str, String** result);
bool InternalizeTwoCharsStringIfExists(String* str, String** result);

View File

@ -459,6 +459,133 @@ uc32 FlatStringReader::Get(int index) {
}
template <typename Char>
class SequentialStringKey : public HashTableKey {
public:
explicit SequentialStringKey(Vector<const Char> string, uint32_t seed)
: string_(string), hash_field_(0), seed_(seed) { }
virtual uint32_t Hash() {
hash_field_ = StringHasher::HashSequentialString<Char>(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<const Char> string_;
uint32_t hash_field_;
uint32_t seed_;
};
class OneByteStringKey : public SequentialStringKey<uint8_t> {
public:
OneByteStringKey(Vector<const uint8_t> str, uint32_t seed)
: SequentialStringKey<uint8_t>(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<SeqOneByteString> 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<const uint8_t> chars(string_->GetChars() + from_, length_);
return String::cast(string)->IsOneByteEqualTo(chars);
}
virtual MaybeObject* AsObject(Heap* heap);
private:
Handle<SeqOneByteString> string_;
int from_;
int length_;
uint32_t hash_field_;
};
class TwoByteStringKey : public SequentialStringKey<uc16> {
public:
explicit TwoByteStringKey(Vector<const uc16> str, uint32_t seed)
: SequentialStringKey<uc16>(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<const char> 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<const char> 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<start_offset>::IterateBody(HeapObject* obj,
#undef READ_BYTE_FIELD
#undef WRITE_BYTE_FIELD
} } // namespace v8::internal
#endif // V8_OBJECTS_INL_H_

View File

@ -14000,142 +14000,23 @@ class RegExpKey : public HashTableKey {
};
// Utf8StringKey carries a vector of chars as key.
class Utf8StringKey : public HashTableKey {
public:
explicit Utf8StringKey(Vector<const char> 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<const char> string_;
uint32_t hash_field_;
int chars_; // Caches the number of characters when computing the hash code.
uint32_t seed_;
};
MaybeObject* OneByteStringKey::AsObject(Heap* heap) {
if (hash_field_ == 0) Hash();
return heap->AllocateOneByteInternalizedString(string_, hash_field_);
}
template <typename Char>
class SequentialStringKey : public HashTableKey {
public:
explicit SequentialStringKey(Vector<const Char> string, uint32_t seed)
: string_(string), hash_field_(0), seed_(seed) { }
uint32_t Hash() {
hash_field_ = StringHasher::HashSequentialString<Char>(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;
}
MaybeObject* SubStringOneByteStringKey::AsObject(Heap* heap) {
if (hash_field_ == 0) Hash();
Vector<const uint8_t> chars(string_->GetChars() + from_, length_);
return heap->AllocateOneByteInternalizedString(chars, hash_field_);
}
uint32_t HashForObject(Object* other) {
return String::cast(other)->Hash();
}
Vector<const Char> string_;
uint32_t hash_field_;
uint32_t seed_;
};
class OneByteStringKey : public SequentialStringKey<uint8_t> {
public:
OneByteStringKey(Vector<const uint8_t> str, uint32_t seed)
: SequentialStringKey<uint8_t>(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<SeqOneByteString> 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<const uint8_t> chars(string_->GetChars() + from_, length_);
return String::cast(string)->IsOneByteEqualTo(chars);
}
MaybeObject* AsObject(Heap* heap) {
if (hash_field_ == 0) Hash();
Vector<const uint8_t> chars(string_->GetChars() + from_, length_);
return heap->AllocateOneByteInternalizedString(chars, hash_field_);
}
private:
Handle<SeqOneByteString> string_;
int from_;
int length_;
uint32_t hash_field_;
};
class TwoByteStringKey : public SequentialStringKey<uc16> {
public:
explicit TwoByteStringKey(Vector<const uc16> str, uint32_t seed)
: SequentialStringKey<uc16>(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<const char> str,
Object** s) {
Utf8StringKey key(str, GetHeap()->HashSeed());
return LookupKey(&key, s);
}
MaybeObject* StringTable::LookupOneByteString(Vector<const uint8_t> str,
Object** s) {
OneByteStringKey key(str, GetHeap()->HashSeed());
return LookupKey(&key, s);
}
MaybeObject* StringTable::LookupSubStringOneByteString(
Handle<SeqOneByteString> str,
int from,
int length,
Object** s) {
SubStringOneByteStringKey key(str, from, length);
return LookupKey(&key, s);
}
MaybeObject* StringTable::LookupTwoByteString(Vector<const uc16> str,
Object** s) {
TwoByteStringKey key(str, GetHeap()->HashSeed());
return LookupKey(&key, s);
}
MaybeObject* StringTable::LookupKey(HashTableKey* key, Object** s) {
int entry = FindEntry(key);

View File

@ -3767,21 +3767,8 @@ class StringTable: public HashTable<StringTableShape, HashTableKey*> {
// 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<const char> str,
Object** s);
MUST_USE_RESULT MaybeObject* LookupOneByteString(
Vector<const uint8_t> str,
Object** s);
MUST_USE_RESULT MaybeObject* LookupSubStringOneByteString(
Handle<SeqOneByteString> str,
int from,
int length,
Object** s);
MUST_USE_RESULT MaybeObject* LookupTwoByteString(
Vector<const uc16> 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<StringTableShape, HashTableKey*> {
static inline StringTable* cast(Object* obj);
private:
MUST_USE_RESULT MaybeObject* LookupKey(HashTableKey* key, Object** s);
template <bool seq_ascii> friend class JsonParser;
DISALLOW_IMPLICIT_CONSTRUCTORS(StringTable);