[runtime] Deconfuse Name::Hash() from Name::hash_field()
This CL * renames Name::hash_field field to raw_hash_field. * all local variables that store raw_hash_field value are also renamed to raw_hash_field where possible. Bug: chromium:1133527, v8:11074 Change-Id: I17313f386110b33a64f629cc2b9d4afd1e06c6c0 Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2471999 Reviewed-by: Peter Marshall <petermarshall@chromium.org> Reviewed-by: Ulan Degenbaev <ulan@chromium.org> Reviewed-by: Jakob Gruber <jgruber@chromium.org> Reviewed-by: Toon Verwaest <verwaest@chromium.org> Commit-Queue: Igor Sheludko <ishell@chromium.org> Cr-Commit-Position: refs/heads/master@{#71114}
This commit is contained in:
parent
424e7a0623
commit
47ddc5b180
@ -65,10 +65,10 @@ void AstRawString::Internalize(LocalIsolate* isolate) {
|
||||
if (literal_bytes_.length() == 0) {
|
||||
set_string(isolate->factory()->empty_string());
|
||||
} else if (is_one_byte()) {
|
||||
OneByteStringKey key(hash_field_, literal_bytes_);
|
||||
OneByteStringKey key(raw_hash_field_, literal_bytes_);
|
||||
set_string(isolate->factory()->InternalizeStringWithKey(&key));
|
||||
} else {
|
||||
TwoByteStringKey key(hash_field_,
|
||||
TwoByteStringKey key(raw_hash_field_,
|
||||
Vector<const uint16_t>::cast(literal_bytes_));
|
||||
set_string(isolate->factory()->InternalizeStringWithKey(&key));
|
||||
}
|
||||
@ -82,9 +82,9 @@ template EXPORT_TEMPLATE_DEFINE(
|
||||
bool AstRawString::AsArrayIndex(uint32_t* index) const {
|
||||
// The StringHasher will set up the hash. Bail out early if we know it
|
||||
// can't be convertible to an array index.
|
||||
if ((hash_field_ & Name::kIsNotIntegerIndexMask) != 0) return false;
|
||||
if ((raw_hash_field_ & Name::kIsNotIntegerIndexMask) != 0) return false;
|
||||
if (length() <= Name::kMaxCachedArrayIndexLength) {
|
||||
*index = Name::ArrayIndexValueBits::decode(hash_field_);
|
||||
*index = Name::ArrayIndexValueBits::decode(raw_hash_field_);
|
||||
return true;
|
||||
}
|
||||
// Might be an index, but too big to cache it. Do the slow conversion. This
|
||||
@ -95,7 +95,7 @@ bool AstRawString::AsArrayIndex(uint32_t* index) const {
|
||||
}
|
||||
|
||||
bool AstRawString::IsIntegerIndex() const {
|
||||
return (hash_field_ & Name::kIsNotIntegerIndexMask) == 0;
|
||||
return (raw_hash_field_ & Name::kIsNotIntegerIndexMask) == 0;
|
||||
}
|
||||
|
||||
bool AstRawString::IsOneByteEqualTo(const char* data) const {
|
||||
@ -250,18 +250,18 @@ AstStringConstants::AstStringConstants(Isolate* isolate, uint64_t hash_seed)
|
||||
string_table_(),
|
||||
hash_seed_(hash_seed) {
|
||||
DCHECK_EQ(ThreadId::Current(), isolate->thread_id());
|
||||
#define F(name, str) \
|
||||
{ \
|
||||
const char* data = str; \
|
||||
Vector<const uint8_t> literal(reinterpret_cast<const uint8_t*>(data), \
|
||||
static_cast<int>(strlen(data))); \
|
||||
uint32_t hash_field = StringHasher::HashSequentialString<uint8_t>( \
|
||||
literal.begin(), literal.length(), hash_seed_); \
|
||||
name##_string_ = zone_.New<AstRawString>(true, literal, hash_field); \
|
||||
/* The Handle returned by the factory is located on the roots */ \
|
||||
/* array, not on the temporary HandleScope, so this is safe. */ \
|
||||
name##_string_->set_string(isolate->factory()->name##_string()); \
|
||||
string_table_.InsertNew(name##_string_, name##_string_->Hash()); \
|
||||
#define F(name, str) \
|
||||
{ \
|
||||
const char* data = str; \
|
||||
Vector<const uint8_t> literal(reinterpret_cast<const uint8_t*>(data), \
|
||||
static_cast<int>(strlen(data))); \
|
||||
uint32_t raw_hash_field = StringHasher::HashSequentialString<uint8_t>( \
|
||||
literal.begin(), literal.length(), hash_seed_); \
|
||||
name##_string_ = zone_.New<AstRawString>(true, literal, raw_hash_field); \
|
||||
/* The Handle returned by the factory is located on the roots */ \
|
||||
/* array, not on the temporary HandleScope, so this is safe. */ \
|
||||
name##_string_->set_string(isolate->factory()->name##_string()); \
|
||||
string_table_.InsertNew(name##_string_, name##_string_->Hash()); \
|
||||
}
|
||||
AST_STRING_CONSTANTS(F)
|
||||
#undef F
|
||||
@ -272,22 +272,22 @@ const AstRawString* AstValueFactory::GetOneByteStringInternal(
|
||||
if (literal.length() == 1 && literal[0] < kMaxOneCharStringValue) {
|
||||
int key = literal[0];
|
||||
if (V8_UNLIKELY(one_character_strings_[key] == nullptr)) {
|
||||
uint32_t hash_field = StringHasher::HashSequentialString<uint8_t>(
|
||||
uint32_t raw_hash_field = StringHasher::HashSequentialString<uint8_t>(
|
||||
literal.begin(), literal.length(), hash_seed_);
|
||||
one_character_strings_[key] = GetString(hash_field, true, literal);
|
||||
one_character_strings_[key] = GetString(raw_hash_field, true, literal);
|
||||
}
|
||||
return one_character_strings_[key];
|
||||
}
|
||||
uint32_t hash_field = StringHasher::HashSequentialString<uint8_t>(
|
||||
uint32_t raw_hash_field = StringHasher::HashSequentialString<uint8_t>(
|
||||
literal.begin(), literal.length(), hash_seed_);
|
||||
return GetString(hash_field, true, literal);
|
||||
return GetString(raw_hash_field, true, literal);
|
||||
}
|
||||
|
||||
const AstRawString* AstValueFactory::GetTwoByteStringInternal(
|
||||
Vector<const uint16_t> literal) {
|
||||
uint32_t hash_field = StringHasher::HashSequentialString<uint16_t>(
|
||||
uint32_t raw_hash_field = StringHasher::HashSequentialString<uint16_t>(
|
||||
literal.begin(), literal.length(), hash_seed_);
|
||||
return GetString(hash_field, false, Vector<const byte>::cast(literal));
|
||||
return GetString(raw_hash_field, false, Vector<const byte>::cast(literal));
|
||||
}
|
||||
|
||||
const AstRawString* AstValueFactory::GetString(Handle<String> literal) {
|
||||
@ -306,7 +306,7 @@ const AstRawString* AstValueFactory::GetString(Handle<String> literal) {
|
||||
const AstRawString* AstValueFactory::CloneFromOtherFactory(
|
||||
const AstRawString* raw_string) {
|
||||
const AstRawString* result = GetString(
|
||||
raw_string->hash_field(), raw_string->is_one_byte(),
|
||||
raw_string->raw_hash_field(), raw_string->is_one_byte(),
|
||||
Vector<const byte>(raw_string->raw_data(), raw_string->byte_length()));
|
||||
return result;
|
||||
}
|
||||
@ -345,12 +345,13 @@ template EXPORT_TEMPLATE_DEFINE(
|
||||
V8_EXPORT_PRIVATE) void AstValueFactory::Internalize(LocalIsolate* isolate);
|
||||
|
||||
const AstRawString* AstValueFactory::GetString(
|
||||
uint32_t hash_field, bool is_one_byte, Vector<const byte> literal_bytes) {
|
||||
uint32_t raw_hash_field, bool is_one_byte,
|
||||
Vector<const byte> literal_bytes) {
|
||||
// literal_bytes here points to whatever the user passed, and this is OK
|
||||
// because we use vector_compare (which checks the contents) to compare
|
||||
// against the AstRawStrings which are in the string_table_. We should not
|
||||
// return this AstRawString.
|
||||
AstRawString key(is_one_byte, literal_bytes, hash_field);
|
||||
AstRawString key(is_one_byte, literal_bytes, raw_hash_field);
|
||||
AstRawStringMap::Entry* entry = string_table_.LookupOrInsert(
|
||||
&key, key.Hash(),
|
||||
[&]() {
|
||||
@ -360,7 +361,7 @@ const AstRawString* AstValueFactory::GetString(
|
||||
memcpy(new_literal_bytes, literal_bytes.begin(), length);
|
||||
AstRawString* new_string = zone()->New<AstRawString>(
|
||||
is_one_byte, Vector<const byte>(new_literal_bytes, length),
|
||||
hash_field);
|
||||
raw_hash_field);
|
||||
CHECK_NOT_NULL(new_string);
|
||||
AddString(new_string);
|
||||
return new_string;
|
||||
|
@ -71,8 +71,8 @@ class AstRawString final : public ZoneObject {
|
||||
bool IsPrivateName() const { return length() > 0 && FirstCharacter() == '#'; }
|
||||
|
||||
// For storing AstRawStrings in a hash map.
|
||||
uint32_t hash_field() const { return hash_field_; }
|
||||
uint32_t Hash() const { return hash_field_ >> Name::kHashShift; }
|
||||
uint32_t raw_hash_field() const { return raw_hash_field_; }
|
||||
uint32_t Hash() const { return raw_hash_field_ >> Name::kHashShift; }
|
||||
|
||||
// This function can be called after internalizing.
|
||||
V8_INLINE Handle<String> string() const {
|
||||
@ -88,10 +88,10 @@ class AstRawString final : public ZoneObject {
|
||||
|
||||
// Members accessed only by the AstValueFactory & related classes:
|
||||
AstRawString(bool is_one_byte, const Vector<const byte>& literal_bytes,
|
||||
uint32_t hash_field)
|
||||
uint32_t raw_hash_field)
|
||||
: next_(nullptr),
|
||||
literal_bytes_(literal_bytes),
|
||||
hash_field_(hash_field),
|
||||
raw_hash_field_(raw_hash_field),
|
||||
is_one_byte_(is_one_byte) {}
|
||||
AstRawString* next() {
|
||||
DCHECK(!has_string_);
|
||||
@ -117,7 +117,7 @@ class AstRawString final : public ZoneObject {
|
||||
};
|
||||
|
||||
Vector<const byte> literal_bytes_; // Memory owned by Zone.
|
||||
uint32_t hash_field_;
|
||||
uint32_t raw_hash_field_;
|
||||
bool is_one_byte_;
|
||||
#ifdef DEBUG
|
||||
// (Debug-only:) Verify the object life-cylce: Some functions may only be
|
||||
@ -369,7 +369,7 @@ class AstValueFactory {
|
||||
V8_EXPORT_PRIVATE const AstRawString* GetOneByteStringInternal(
|
||||
Vector<const uint8_t> literal);
|
||||
const AstRawString* GetTwoByteStringInternal(Vector<const uint16_t> literal);
|
||||
const AstRawString* GetString(uint32_t hash, bool is_one_byte,
|
||||
const AstRawString* GetString(uint32_t raw_hash_field, bool is_one_byte,
|
||||
Vector<const byte> literal_bytes);
|
||||
|
||||
// All strings are copied here.
|
||||
|
@ -336,7 +336,7 @@ TNode<String> StringBuiltinsAssembler::AllocateConsString(TNode<Uint32T> length,
|
||||
TNode<HeapObject> result = AllocateInNewSpace(ConsString::kSize);
|
||||
StoreMapNoWriteBarrier(result, result_map);
|
||||
StoreObjectFieldNoWriteBarrier(result, ConsString::kLengthOffset, length);
|
||||
StoreObjectFieldNoWriteBarrier(result, ConsString::kHashFieldOffset,
|
||||
StoreObjectFieldNoWriteBarrier(result, ConsString::kRawHashFieldOffset,
|
||||
Int32Constant(String::kEmptyHashField));
|
||||
StoreObjectFieldNoWriteBarrier(result, ConsString::kFirstOffset, left);
|
||||
StoreObjectFieldNoWriteBarrier(result, ConsString::kSecondOffset, right);
|
||||
|
@ -109,8 +109,8 @@ macro NumberToStringSmi(x: int32, radix: int32): String labels Slow {
|
||||
// In sync with Factory::SmiToString: If radix = 10 and positive number,
|
||||
// update hash for string.
|
||||
if (radix == 10) {
|
||||
assert(strSeq.hash_field == kNameEmptyHashField);
|
||||
strSeq.hash_field = MakeArrayIndexHash(Unsigned(x), Unsigned(length));
|
||||
assert(strSeq.raw_hash_field == kNameEmptyHashField);
|
||||
strSeq.raw_hash_field = MakeArrayIndexHash(Unsigned(x), Unsigned(length));
|
||||
}
|
||||
}
|
||||
return strSeq;
|
||||
@ -236,7 +236,7 @@ transitioning javascript builtin NumberParseFloat(
|
||||
}
|
||||
} label String(s: String) {
|
||||
// Check if the string is a cached array index.
|
||||
const hash: NameHash = s.hash_field;
|
||||
const hash: NameHash = s.raw_hash_field;
|
||||
if (!hash.is_not_integer_index_mask &&
|
||||
hash.array_index_length < kMaxCachedArrayIndexLength) {
|
||||
const arrayIndex: uint32 = hash.array_index_value;
|
||||
@ -287,7 +287,7 @@ transitioning builtin ParseInt(implicit context: Context)(
|
||||
return ChangeInt32ToTagged(i);
|
||||
} label String(s: String) {
|
||||
// Check if the string is a cached array index.
|
||||
const hash: NameHash = s.hash_field;
|
||||
const hash: NameHash = s.raw_hash_field;
|
||||
if (!hash.is_not_integer_index_mask &&
|
||||
hash.array_index_length < kMaxCachedArrayIndexLength) {
|
||||
const arrayIndex: uint32 = hash.array_index_value;
|
||||
|
@ -1816,19 +1816,19 @@ TNode<IntPtrT> CodeStubAssembler::LoadJSReceiverIdentityHash(
|
||||
}
|
||||
|
||||
TNode<Uint32T> CodeStubAssembler::LoadNameHashAssumeComputed(TNode<Name> name) {
|
||||
TNode<Uint32T> hash_field = LoadNameHashField(name);
|
||||
TNode<Uint32T> hash_field = LoadNameRawHashField(name);
|
||||
CSA_ASSERT(this, IsClearWord32(hash_field, Name::kHashNotComputedMask));
|
||||
return Unsigned(Word32Shr(hash_field, Int32Constant(Name::kHashShift)));
|
||||
}
|
||||
|
||||
TNode<Uint32T> CodeStubAssembler::LoadNameHash(TNode<Name> name,
|
||||
Label* if_hash_not_computed) {
|
||||
TNode<Uint32T> hash_field = LoadNameHashField(name);
|
||||
TNode<Uint32T> raw_hash_field = LoadNameRawHashField(name);
|
||||
if (if_hash_not_computed != nullptr) {
|
||||
GotoIf(IsSetWord32(hash_field, Name::kHashNotComputedMask),
|
||||
GotoIf(IsSetWord32(raw_hash_field, Name::kHashNotComputedMask),
|
||||
if_hash_not_computed);
|
||||
}
|
||||
return Unsigned(Word32Shr(hash_field, Int32Constant(Name::kHashShift)));
|
||||
return Unsigned(Word32Shr(raw_hash_field, Int32Constant(Name::kHashShift)));
|
||||
}
|
||||
|
||||
TNode<Smi> CodeStubAssembler::LoadStringLengthAsSmi(TNode<String> string) {
|
||||
@ -3206,7 +3206,7 @@ TNode<String> CodeStubAssembler::AllocateSeqOneByteString(
|
||||
StoreMapNoWriteBarrier(result, RootIndex::kOneByteStringMap);
|
||||
StoreObjectFieldNoWriteBarrier(result, SeqOneByteString::kLengthOffset,
|
||||
Uint32Constant(length));
|
||||
StoreObjectFieldNoWriteBarrier(result, SeqOneByteString::kHashFieldOffset,
|
||||
StoreObjectFieldNoWriteBarrier(result, SeqOneByteString::kRawHashFieldOffset,
|
||||
Int32Constant(String::kEmptyHashField));
|
||||
return CAST(result);
|
||||
}
|
||||
@ -3228,7 +3228,7 @@ TNode<String> CodeStubAssembler::AllocateSeqTwoByteString(
|
||||
StoreMapNoWriteBarrier(result, RootIndex::kStringMap);
|
||||
StoreObjectFieldNoWriteBarrier(result, SeqTwoByteString::kLengthOffset,
|
||||
Uint32Constant(length));
|
||||
StoreObjectFieldNoWriteBarrier(result, SeqTwoByteString::kHashFieldOffset,
|
||||
StoreObjectFieldNoWriteBarrier(result, SeqTwoByteString::kRawHashFieldOffset,
|
||||
Int32Constant(String::kEmptyHashField));
|
||||
return CAST(result);
|
||||
}
|
||||
@ -3242,7 +3242,7 @@ TNode<String> CodeStubAssembler::AllocateSlicedString(RootIndex map_root_index,
|
||||
TNode<HeapObject> result = Allocate(SlicedString::kSize);
|
||||
DCHECK(RootsTable::IsImmortalImmovable(map_root_index));
|
||||
StoreMapNoWriteBarrier(result, map_root_index);
|
||||
StoreObjectFieldNoWriteBarrier(result, SlicedString::kHashFieldOffset,
|
||||
StoreObjectFieldNoWriteBarrier(result, SlicedString::kRawHashFieldOffset,
|
||||
Int32Constant(String::kEmptyHashField));
|
||||
StoreObjectFieldNoWriteBarrier(result, SlicedString::kLengthOffset, length);
|
||||
StoreObjectFieldNoWriteBarrier(result, SlicedString::kParentOffset, parent);
|
||||
@ -6173,7 +6173,7 @@ TNode<BoolT> CodeStubAssembler::IsUniqueNameNoIndex(TNode<HeapObject> object) {
|
||||
return Select<BoolT>(
|
||||
IsInternalizedStringInstanceType(instance_type),
|
||||
[=] {
|
||||
return IsSetWord32(LoadNameHashField(CAST(object)),
|
||||
return IsSetWord32(LoadNameRawHashField(CAST(object)),
|
||||
Name::kIsNotIntegerIndexMask);
|
||||
},
|
||||
[=] { return IsSymbolInstanceType(instance_type); });
|
||||
@ -6191,7 +6191,7 @@ TNode<BoolT> CodeStubAssembler::IsUniqueNameNoCachedIndex(
|
||||
return Select<BoolT>(
|
||||
IsInternalizedStringInstanceType(instance_type),
|
||||
[=] {
|
||||
return IsSetWord32(LoadNameHashField(CAST(object)),
|
||||
return IsSetWord32(LoadNameRawHashField(CAST(object)),
|
||||
Name::kDoesNotContainCachedArrayIndexMask);
|
||||
},
|
||||
[=] { return IsSymbolInstanceType(instance_type); });
|
||||
@ -6672,12 +6672,12 @@ TNode<Number> CodeStubAssembler::StringToNumber(TNode<String> input) {
|
||||
TVARIABLE(Number, var_result);
|
||||
|
||||
// Check if string has a cached array index.
|
||||
TNode<Uint32T> hash = LoadNameHashField(input);
|
||||
GotoIf(IsSetWord32(hash, Name::kDoesNotContainCachedArrayIndexMask),
|
||||
TNode<Uint32T> raw_hash_field = LoadNameRawHashField(input);
|
||||
GotoIf(IsSetWord32(raw_hash_field, Name::kDoesNotContainCachedArrayIndexMask),
|
||||
&runtime);
|
||||
|
||||
var_result =
|
||||
SmiTag(Signed(DecodeWordFromWord32<String::ArrayIndexValueBits>(hash)));
|
||||
var_result = SmiTag(Signed(
|
||||
DecodeWordFromWord32<String::ArrayIndexValueBits>(raw_hash_field)));
|
||||
Goto(&end);
|
||||
|
||||
BIND(&runtime);
|
||||
@ -7439,12 +7439,14 @@ void CodeStubAssembler::TryToName(SloppyTNode<Object> key, Label* if_keyisindex,
|
||||
{
|
||||
Label if_thinstring(this), if_has_cached_index(this);
|
||||
|
||||
TNode<Uint32T> hash = LoadNameHashField(CAST(key));
|
||||
GotoIf(IsClearWord32(hash, Name::kDoesNotContainCachedArrayIndexMask),
|
||||
TNode<Uint32T> raw_hash_field = LoadNameRawHashField(CAST(key));
|
||||
GotoIf(IsClearWord32(raw_hash_field,
|
||||
Name::kDoesNotContainCachedArrayIndexMask),
|
||||
&if_has_cached_index);
|
||||
// No cached array index. If the string knows that it contains an index,
|
||||
// then it must be an uncacheable index. Handle this case in the runtime.
|
||||
GotoIf(IsClearWord32(hash, Name::kIsNotIntegerIndexMask), if_bailout);
|
||||
GotoIf(IsClearWord32(raw_hash_field, Name::kIsNotIntegerIndexMask),
|
||||
if_bailout);
|
||||
|
||||
GotoIf(InstanceTypeEqual(var_instance_type.value(), THIN_STRING_TYPE),
|
||||
&if_thinstring);
|
||||
@ -7468,8 +7470,8 @@ void CodeStubAssembler::TryToName(SloppyTNode<Object> key, Label* if_keyisindex,
|
||||
|
||||
BIND(&if_has_cached_index);
|
||||
{
|
||||
TNode<IntPtrT> index =
|
||||
Signed(DecodeWordFromWord32<String::ArrayIndexValueBits>(hash));
|
||||
TNode<IntPtrT> index = Signed(
|
||||
DecodeWordFromWord32<String::ArrayIndexValueBits>(raw_hash_field));
|
||||
CSA_ASSERT(this, IntPtrLessThan(index, IntPtrConstant(INT_MAX)));
|
||||
*var_index = index;
|
||||
Goto(if_keyisindex);
|
||||
|
@ -680,8 +680,8 @@ FieldAccess AccessBuilder::ForModuleRegularImports() {
|
||||
}
|
||||
|
||||
// static
|
||||
FieldAccess AccessBuilder::ForNameHashField() {
|
||||
FieldAccess access = {kTaggedBase, Name::kHashFieldOffset,
|
||||
FieldAccess AccessBuilder::ForNameRawHashField() {
|
||||
FieldAccess access = {kTaggedBase, Name::kRawHashFieldOffset,
|
||||
Handle<Name>(), MaybeHandle<Map>(),
|
||||
Type::Unsigned32(), MachineType::Uint32(),
|
||||
kNoWriteBarrier};
|
||||
|
@ -221,8 +221,8 @@ class V8_EXPORT_PRIVATE AccessBuilder final
|
||||
// Provides access to Module::regular_imports() field.
|
||||
static FieldAccess ForModuleRegularImports();
|
||||
|
||||
// Provides access to Name::hash_field() field.
|
||||
static FieldAccess ForNameHashField();
|
||||
// Provides access to Name::raw_hash_field() field.
|
||||
static FieldAccess ForNameRawHashField();
|
||||
|
||||
// Provides access to String::length() field.
|
||||
static FieldAccess ForStringLength();
|
||||
|
@ -3917,7 +3917,7 @@ Node* EffectControlLinearizer::LowerNewConsString(Node* node) {
|
||||
Node* result =
|
||||
__ Allocate(AllocationType::kYoung, __ IntPtrConstant(ConsString::kSize));
|
||||
__ StoreField(AccessBuilder::ForMap(), result, result_map);
|
||||
__ StoreField(AccessBuilder::ForNameHashField(), result,
|
||||
__ StoreField(AccessBuilder::ForNameRawHashField(), result,
|
||||
__ Int32Constant(Name::kEmptyHashField));
|
||||
__ StoreField(AccessBuilder::ForStringLength(), result, length);
|
||||
__ StoreField(AccessBuilder::ForConsStringFirst(), result, first);
|
||||
@ -4227,7 +4227,7 @@ Node* EffectControlLinearizer::LowerStringFromSingleCharCode(Node* node) {
|
||||
__ IntPtrConstant(SeqOneByteString::SizeFor(1)));
|
||||
__ StoreField(AccessBuilder::ForMap(), vtrue2,
|
||||
__ HeapConstant(factory()->one_byte_string_map()));
|
||||
__ StoreField(AccessBuilder::ForNameHashField(), vtrue2,
|
||||
__ StoreField(AccessBuilder::ForNameRawHashField(), vtrue2,
|
||||
__ Int32Constant(Name::kEmptyHashField));
|
||||
__ StoreField(AccessBuilder::ForStringLength(), vtrue2,
|
||||
__ Int32Constant(1));
|
||||
@ -4252,7 +4252,7 @@ Node* EffectControlLinearizer::LowerStringFromSingleCharCode(Node* node) {
|
||||
__ IntPtrConstant(SeqTwoByteString::SizeFor(1)));
|
||||
__ StoreField(AccessBuilder::ForMap(), vfalse1,
|
||||
__ HeapConstant(factory()->string_map()));
|
||||
__ StoreField(AccessBuilder::ForNameHashField(), vfalse1,
|
||||
__ StoreField(AccessBuilder::ForNameRawHashField(), vfalse1,
|
||||
__ Int32Constant(Name::kEmptyHashField));
|
||||
__ StoreField(AccessBuilder::ForStringLength(), vfalse1,
|
||||
__ Int32Constant(1));
|
||||
@ -4353,7 +4353,7 @@ Node* EffectControlLinearizer::LowerStringFromSingleCodePoint(Node* node) {
|
||||
__ IntPtrConstant(SeqOneByteString::SizeFor(1)));
|
||||
__ StoreField(AccessBuilder::ForMap(), vtrue2,
|
||||
__ HeapConstant(factory()->one_byte_string_map()));
|
||||
__ StoreField(AccessBuilder::ForNameHashField(), vtrue2,
|
||||
__ StoreField(AccessBuilder::ForNameRawHashField(), vtrue2,
|
||||
__ Int32Constant(Name::kEmptyHashField));
|
||||
__ StoreField(AccessBuilder::ForStringLength(), vtrue2,
|
||||
__ Int32Constant(1));
|
||||
@ -4378,7 +4378,7 @@ Node* EffectControlLinearizer::LowerStringFromSingleCodePoint(Node* node) {
|
||||
__ IntPtrConstant(SeqTwoByteString::SizeFor(1)));
|
||||
__ StoreField(AccessBuilder::ForMap(), vfalse1,
|
||||
__ HeapConstant(factory()->string_map()));
|
||||
__ StoreField(AccessBuilder::ForNameHashField(), vfalse1,
|
||||
__ StoreField(AccessBuilder::ForNameRawHashField(), vfalse1,
|
||||
__ IntPtrConstant(Name::kEmptyHashField));
|
||||
__ StoreField(AccessBuilder::ForStringLength(), vfalse1,
|
||||
__ Int32Constant(1));
|
||||
@ -4418,7 +4418,7 @@ Node* EffectControlLinearizer::LowerStringFromSingleCodePoint(Node* node) {
|
||||
__ IntPtrConstant(SeqTwoByteString::SizeFor(2)));
|
||||
__ StoreField(AccessBuilder::ForMap(), vfalse0,
|
||||
__ HeapConstant(factory()->string_map()));
|
||||
__ StoreField(AccessBuilder::ForNameHashField(), vfalse0,
|
||||
__ StoreField(AccessBuilder::ForNameRawHashField(), vfalse0,
|
||||
__ Int32Constant(Name::kEmptyHashField));
|
||||
__ StoreField(AccessBuilder::ForStringLength(), vfalse0,
|
||||
__ Int32Constant(2));
|
||||
|
@ -648,7 +648,7 @@ void JSRegExpStringIterator::JSRegExpStringIteratorPrint(
|
||||
|
||||
void Symbol::SymbolPrint(std::ostream& os) { // NOLINT
|
||||
PrintHeader(os, "Symbol");
|
||||
os << "\n - hash: " << Hash();
|
||||
os << "\n - hash: " << hash();
|
||||
os << "\n - description: " << Brief(description());
|
||||
if (description().IsUndefined()) {
|
||||
os << " (" << PrivateSymbolToName() << ")";
|
||||
|
@ -504,9 +504,9 @@ Handle<String> FactoryBase<Impl>::InternalizeString(
|
||||
|
||||
template <typename Impl>
|
||||
Handle<SeqOneByteString> FactoryBase<Impl>::NewOneByteInternalizedString(
|
||||
const Vector<const uint8_t>& str, uint32_t hash_field) {
|
||||
const Vector<const uint8_t>& str, uint32_t raw_hash_field) {
|
||||
Handle<SeqOneByteString> result =
|
||||
AllocateRawOneByteInternalizedString(str.length(), hash_field);
|
||||
AllocateRawOneByteInternalizedString(str.length(), raw_hash_field);
|
||||
DisallowHeapAllocation no_gc;
|
||||
MemCopy(result->GetChars(no_gc), str.begin(), str.length());
|
||||
return result;
|
||||
@ -514,9 +514,9 @@ Handle<SeqOneByteString> FactoryBase<Impl>::NewOneByteInternalizedString(
|
||||
|
||||
template <typename Impl>
|
||||
Handle<SeqTwoByteString> FactoryBase<Impl>::NewTwoByteInternalizedString(
|
||||
const Vector<const uc16>& str, uint32_t hash_field) {
|
||||
const Vector<const uc16>& str, uint32_t raw_hash_field) {
|
||||
Handle<SeqTwoByteString> result =
|
||||
AllocateRawTwoByteInternalizedString(str.length(), hash_field);
|
||||
AllocateRawTwoByteInternalizedString(str.length(), raw_hash_field);
|
||||
DisallowHeapAllocation no_gc;
|
||||
MemCopy(result->GetChars(no_gc), str.begin(), str.length() * kUC16Size);
|
||||
return result;
|
||||
@ -537,7 +537,7 @@ MaybeHandle<SeqOneByteString> FactoryBase<Impl>::NewRawOneByteString(
|
||||
Handle<SeqOneByteString> string =
|
||||
handle(SeqOneByteString::cast(result), isolate());
|
||||
string->set_length(length);
|
||||
string->set_hash_field(String::kEmptyHashField);
|
||||
string->set_raw_hash_field(String::kEmptyHashField);
|
||||
DCHECK_EQ(size, string->Size());
|
||||
return string;
|
||||
}
|
||||
@ -557,7 +557,7 @@ MaybeHandle<SeqTwoByteString> FactoryBase<Impl>::NewRawTwoByteString(
|
||||
Handle<SeqTwoByteString> string =
|
||||
handle(SeqTwoByteString::cast(result), isolate());
|
||||
string->set_length(length);
|
||||
string->set_hash_field(String::kEmptyHashField);
|
||||
string->set_raw_hash_field(String::kEmptyHashField);
|
||||
DCHECK_EQ(size, string->Size());
|
||||
return string;
|
||||
}
|
||||
@ -651,7 +651,7 @@ Handle<String> FactoryBase<Impl>::NewConsString(Handle<String> left,
|
||||
DisallowHeapAllocation no_gc;
|
||||
WriteBarrierMode mode = result->GetWriteBarrierMode(no_gc);
|
||||
|
||||
result->set_hash_field(String::kEmptyHashField);
|
||||
result->set_raw_hash_field(String::kEmptyHashField);
|
||||
result->set_length(length);
|
||||
result->set_first(*left, mode);
|
||||
result->set_second(*right, mode);
|
||||
@ -734,8 +734,8 @@ Handle<ClassPositions> FactoryBase<Impl>::NewClassPositions(int start,
|
||||
|
||||
template <typename Impl>
|
||||
Handle<SeqOneByteString>
|
||||
FactoryBase<Impl>::AllocateRawOneByteInternalizedString(int length,
|
||||
uint32_t hash_field) {
|
||||
FactoryBase<Impl>::AllocateRawOneByteInternalizedString(
|
||||
int length, uint32_t raw_hash_field) {
|
||||
CHECK_GE(String::kMaxLength, length);
|
||||
// The canonical empty_string is the only zero-length string we allow.
|
||||
DCHECK_IMPLIES(length == 0, !impl()->EmptyStringRootIsInitialized());
|
||||
@ -750,15 +750,15 @@ FactoryBase<Impl>::AllocateRawOneByteInternalizedString(int length,
|
||||
Handle<SeqOneByteString> answer =
|
||||
handle(SeqOneByteString::cast(result), isolate());
|
||||
answer->set_length(length);
|
||||
answer->set_hash_field(hash_field);
|
||||
answer->set_raw_hash_field(raw_hash_field);
|
||||
DCHECK_EQ(size, answer->Size());
|
||||
return answer;
|
||||
}
|
||||
|
||||
template <typename Impl>
|
||||
Handle<SeqTwoByteString>
|
||||
FactoryBase<Impl>::AllocateRawTwoByteInternalizedString(int length,
|
||||
uint32_t hash_field) {
|
||||
FactoryBase<Impl>::AllocateRawTwoByteInternalizedString(
|
||||
int length, uint32_t raw_hash_field) {
|
||||
CHECK_GE(String::kMaxLength, length);
|
||||
DCHECK_NE(0, length); // Use Heap::empty_string() instead.
|
||||
|
||||
@ -769,7 +769,7 @@ FactoryBase<Impl>::AllocateRawTwoByteInternalizedString(int length,
|
||||
Handle<SeqTwoByteString> answer =
|
||||
handle(SeqTwoByteString::cast(result), isolate());
|
||||
answer->set_length(length);
|
||||
answer->set_hash_field(hash_field);
|
||||
answer->set_raw_hash_field(raw_hash_field);
|
||||
DCHECK_EQ(size, result.Size());
|
||||
return answer;
|
||||
}
|
||||
|
@ -151,14 +151,14 @@ class EXPORT_TEMPLATE_DECLARE(V8_EXPORT_PRIVATE) FactoryBase {
|
||||
Handle<String> InternalizeStringWithKey(StringTableKey* key);
|
||||
|
||||
Handle<SeqOneByteString> NewOneByteInternalizedString(
|
||||
const Vector<const uint8_t>& str, uint32_t hash_field);
|
||||
const Vector<const uint8_t>& str, uint32_t raw_hash_field);
|
||||
Handle<SeqTwoByteString> NewTwoByteInternalizedString(
|
||||
const Vector<const uc16>& str, uint32_t hash_field);
|
||||
const Vector<const uc16>& str, uint32_t raw_hash_field);
|
||||
|
||||
Handle<SeqOneByteString> AllocateRawOneByteInternalizedString(
|
||||
int length, uint32_t hash_field);
|
||||
int length, uint32_t raw_hash_field);
|
||||
Handle<SeqTwoByteString> AllocateRawTwoByteInternalizedString(
|
||||
int length, uint32_t hash_field);
|
||||
int length, uint32_t raw_hash_field);
|
||||
|
||||
// Allocates and partially initializes an one-byte or two-byte String. The
|
||||
// characters of the string are uninitialized. Currently used in regexp code
|
||||
|
@ -763,7 +763,7 @@ Handle<String> Factory::AllocateInternalizedStringImpl(T t, int chars,
|
||||
map);
|
||||
Handle<String> answer(String::cast(result), isolate());
|
||||
answer->set_length(chars);
|
||||
answer->set_hash_field(hash_field);
|
||||
answer->set_raw_hash_field(hash_field);
|
||||
DCHECK_EQ(size, answer->Size());
|
||||
DisallowHeapAllocation no_gc;
|
||||
|
||||
@ -824,7 +824,7 @@ Handle<StringClass> Factory::InternalizeExternalString(Handle<String> string) {
|
||||
StringClass::cast(New(map, AllocationType::kOld)), isolate());
|
||||
external_string->AllocateExternalPointerEntries(isolate());
|
||||
external_string->set_length(cast_string->length());
|
||||
external_string->set_hash_field(cast_string->hash_field());
|
||||
external_string->set_raw_hash_field(cast_string->raw_hash_field());
|
||||
external_string->SetResource(isolate(), nullptr);
|
||||
isolate()->heap()->RegisterExternalString(*external_string);
|
||||
return external_string;
|
||||
@ -928,7 +928,7 @@ Handle<String> Factory::NewProperSubString(Handle<String> str, int begin,
|
||||
Handle<SlicedString> slice(
|
||||
SlicedString::cast(New(map, AllocationType::kYoung)), isolate());
|
||||
|
||||
slice->set_hash_field(String::kEmptyHashField);
|
||||
slice->set_raw_hash_field(String::kEmptyHashField);
|
||||
slice->set_length(length);
|
||||
slice->set_parent(*str);
|
||||
slice->set_offset(offset);
|
||||
@ -950,7 +950,7 @@ MaybeHandle<String> Factory::NewExternalStringFromOneByte(
|
||||
ExternalOneByteString::cast(New(map, AllocationType::kOld)), isolate());
|
||||
external_string->AllocateExternalPointerEntries(isolate());
|
||||
external_string->set_length(static_cast<int>(length));
|
||||
external_string->set_hash_field(String::kEmptyHashField);
|
||||
external_string->set_raw_hash_field(String::kEmptyHashField);
|
||||
external_string->SetResource(isolate(), resource);
|
||||
isolate()->heap()->RegisterExternalString(*external_string);
|
||||
|
||||
@ -971,7 +971,7 @@ MaybeHandle<String> Factory::NewExternalStringFromTwoByte(
|
||||
ExternalTwoByteString::cast(New(map, AllocationType::kOld)), isolate());
|
||||
external_string->AllocateExternalPointerEntries(isolate());
|
||||
external_string->set_length(static_cast<int>(length));
|
||||
external_string->set_hash_field(String::kEmptyHashField);
|
||||
external_string->set_raw_hash_field(String::kEmptyHashField);
|
||||
external_string->SetResource(isolate(), resource);
|
||||
isolate()->heap()->RegisterExternalString(*external_string);
|
||||
|
||||
@ -1002,8 +1002,8 @@ Handle<Symbol> Factory::NewSymbol(AllocationType allocation) {
|
||||
int hash = isolate()->GenerateIdentityHash(Name::kHashBitMask);
|
||||
|
||||
Handle<Symbol> symbol(Symbol::cast(result), isolate());
|
||||
symbol->set_hash_field(Name::kIsNotIntegerIndexMask |
|
||||
(hash << Name::kHashShift));
|
||||
symbol->set_raw_hash_field(Name::kIsNotIntegerIndexMask |
|
||||
(hash << Name::kHashShift));
|
||||
symbol->set_description(*undefined_value());
|
||||
symbol->set_flags(0);
|
||||
DCHECK(!symbol->is_private());
|
||||
@ -2832,10 +2832,11 @@ inline Handle<String> Factory::SmiToString(Smi number, NumberCacheMode mode) {
|
||||
// Compute the hash here (rather than letting the caller take care of it) so
|
||||
// that the "cache hit" case above doesn't have to bother with it.
|
||||
STATIC_ASSERT(Smi::kMaxValue <= std::numeric_limits<uint32_t>::max());
|
||||
if (result->hash_field() == String::kEmptyHashField && number.value() >= 0) {
|
||||
uint32_t field = StringHasher::MakeArrayIndexHash(
|
||||
if (result->raw_hash_field() == String::kEmptyHashField &&
|
||||
number.value() >= 0) {
|
||||
uint32_t raw_hash_field = StringHasher::MakeArrayIndexHash(
|
||||
static_cast<uint32_t>(number.value()), result->length());
|
||||
result->set_hash_field(field);
|
||||
result->set_raw_hash_field(raw_hash_field);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
@ -2868,10 +2869,10 @@ Handle<String> Factory::SizeToString(size_t value, bool check_cache) {
|
||||
result = NewStringFromAsciiChecked(string);
|
||||
}
|
||||
if (value <= JSArray::kMaxArrayIndex &&
|
||||
result->hash_field() == String::kEmptyHashField) {
|
||||
uint32_t field = StringHasher::MakeArrayIndexHash(
|
||||
result->raw_hash_field() == String::kEmptyHashField) {
|
||||
uint32_t raw_hash_field = StringHasher::MakeArrayIndexHash(
|
||||
static_cast<uint32_t>(value), result->length());
|
||||
result->set_hash_field(field);
|
||||
result->set_raw_hash_field(raw_hash_field);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
@ -2554,9 +2554,9 @@ enum AccessorAssembler::StubCacheTable : int {
|
||||
TNode<IntPtrT> AccessorAssembler::StubCachePrimaryOffset(TNode<Name> name,
|
||||
TNode<Map> map) {
|
||||
// Compute the hash of the name (use entire hash field).
|
||||
TNode<Uint32T> hash_field = LoadNameHashField(name);
|
||||
TNode<Uint32T> raw_hash_field = LoadNameRawHashField(name);
|
||||
CSA_ASSERT(this,
|
||||
Word32Equal(Word32And(hash_field,
|
||||
Word32Equal(Word32And(raw_hash_field,
|
||||
Int32Constant(Name::kHashNotComputedMask)),
|
||||
Int32Constant(0)));
|
||||
|
||||
@ -2568,7 +2568,7 @@ TNode<IntPtrT> AccessorAssembler::StubCachePrimaryOffset(TNode<Name> name,
|
||||
TNode<Int32T> map32 = TruncateIntPtrToInt32(UncheckedCast<IntPtrT>(
|
||||
WordXor(map_word, WordShr(map_word, StubCache::kMapKeyShift))));
|
||||
// Base the offset on a simple combination of name and map.
|
||||
TNode<Word32T> hash = Int32Add(hash_field, map32);
|
||||
TNode<Word32T> hash = Int32Add(raw_hash_field, map32);
|
||||
uint32_t mask = (StubCache::kPrimaryTableSize - 1)
|
||||
<< StubCache::kCacheIndexShift;
|
||||
TNode<UintPtrT> result =
|
||||
|
@ -32,7 +32,7 @@ void StubCache::Initialize() {
|
||||
int StubCache::PrimaryOffset(Name name, Map map) {
|
||||
// Compute the hash of the name (use entire hash field).
|
||||
DCHECK(name.HasHashCode());
|
||||
uint32_t field = name.hash_field();
|
||||
uint32_t field = name.raw_hash_field();
|
||||
// Using only the low bits in 64-bit mode is unlikely to increase the
|
||||
// risk of collision even if the heap is spread over an area larger than
|
||||
// 4Gb (and not at all if it isn't).
|
||||
|
@ -17,7 +17,7 @@ int DescriptorLookupCache::Hash(Map source, Name name) {
|
||||
DCHECK(name.IsUniqueName());
|
||||
// Uses only lower 32 bits if pointers are larger.
|
||||
uint32_t source_hash = static_cast<uint32_t>(source.ptr()) >> kTaggedSizeLog2;
|
||||
uint32_t name_hash = name.hash_field();
|
||||
uint32_t name_hash = name.hash();
|
||||
return (source_hash ^ name_hash) % kLength;
|
||||
}
|
||||
|
||||
|
@ -86,18 +86,18 @@ bool Name::IsHashFieldComputed(uint32_t field) {
|
||||
return (field & kHashNotComputedMask) == 0;
|
||||
}
|
||||
|
||||
bool Name::HasHashCode() { return IsHashFieldComputed(hash_field()); }
|
||||
bool Name::HasHashCode() { return IsHashFieldComputed(raw_hash_field()); }
|
||||
|
||||
uint32_t Name::Hash() {
|
||||
// Fast case: has hash code already been computed?
|
||||
uint32_t field = hash_field();
|
||||
uint32_t field = raw_hash_field();
|
||||
if (IsHashFieldComputed(field)) return field >> kHashShift;
|
||||
// Slow case: compute hash code and set it. Has to be a string.
|
||||
return String::cast(*this).ComputeAndSetHash();
|
||||
}
|
||||
|
||||
uint32_t Name::hash() const {
|
||||
uint32_t field = hash_field();
|
||||
uint32_t field = raw_hash_field();
|
||||
DCHECK(IsHashFieldComputed(field));
|
||||
return field >> kHashShift;
|
||||
}
|
||||
@ -133,8 +133,8 @@ bool Name::AsIntegerIndex(size_t* index) {
|
||||
}
|
||||
|
||||
// static
|
||||
bool Name::ContainsCachedArrayIndex(uint32_t hash) {
|
||||
return (hash & Name::kDoesNotContainCachedArrayIndexMask) == 0;
|
||||
bool Name::ContainsCachedArrayIndex(uint32_t raw_hash_field) {
|
||||
return (raw_hash_field & Name::kDoesNotContainCachedArrayIndexMask) == 0;
|
||||
}
|
||||
|
||||
} // namespace internal
|
||||
|
@ -5,7 +5,7 @@
|
||||
@abstract
|
||||
@generateCppClass
|
||||
extern class Name extends PrimitiveHeapObject {
|
||||
hash_field: NameHash;
|
||||
raw_hash_field: NameHash;
|
||||
}
|
||||
|
||||
bitfield struct NameHash extends uint32 {
|
||||
|
@ -275,9 +275,9 @@ class SequentialStringKey final : public StringTableKey {
|
||||
chars.begin(), chars.length(), seed),
|
||||
chars, convert) {}
|
||||
|
||||
SequentialStringKey(int hash, const Vector<const Char>& chars,
|
||||
SequentialStringKey(int raw_hash_field, const Vector<const Char>& chars,
|
||||
bool convert = false)
|
||||
: StringTableKey(hash, chars.length()),
|
||||
: StringTableKey(raw_hash_field, chars.length()),
|
||||
chars_(chars),
|
||||
convert_(convert) {}
|
||||
|
||||
@ -294,19 +294,19 @@ class SequentialStringKey final : public StringTableKey {
|
||||
Handle<String> AsHandle(Isolate* isolate) {
|
||||
if (sizeof(Char) == 1) {
|
||||
return isolate->factory()->NewOneByteInternalizedString(
|
||||
Vector<const uint8_t>::cast(chars_), hash_field());
|
||||
Vector<const uint8_t>::cast(chars_), raw_hash_field());
|
||||
}
|
||||
return isolate->factory()->NewTwoByteInternalizedString(
|
||||
Vector<const uint16_t>::cast(chars_), hash_field());
|
||||
Vector<const uint16_t>::cast(chars_), raw_hash_field());
|
||||
}
|
||||
|
||||
Handle<String> AsHandle(LocalIsolate* isolate) {
|
||||
if (sizeof(Char) == 1) {
|
||||
return isolate->factory()->NewOneByteInternalizedString(
|
||||
Vector<const uint8_t>::cast(chars_), hash_field());
|
||||
Vector<const uint8_t>::cast(chars_), raw_hash_field());
|
||||
}
|
||||
return isolate->factory()->NewTwoByteInternalizedString(
|
||||
Vector<const uint16_t>::cast(chars_), hash_field());
|
||||
Vector<const uint16_t>::cast(chars_), raw_hash_field());
|
||||
}
|
||||
|
||||
private:
|
||||
@ -337,9 +337,9 @@ class SeqSubStringKey final : public StringTableKey {
|
||||
convert_(convert) {
|
||||
// We have to set the hash later.
|
||||
DisallowHeapAllocation no_gc;
|
||||
uint32_t hash = StringHasher::HashSequentialString(
|
||||
uint32_t raw_hash_field = StringHasher::HashSequentialString(
|
||||
string->GetChars(no_gc) + from, len, HashSeed(isolate));
|
||||
set_hash_field(hash);
|
||||
set_raw_hash_field(raw_hash_field);
|
||||
|
||||
DCHECK_LE(0, length());
|
||||
DCHECK_LE(from_ + length(), string_->length());
|
||||
@ -366,15 +366,15 @@ class SeqSubStringKey final : public StringTableKey {
|
||||
if (sizeof(Char) == 1 || (sizeof(Char) == 2 && convert_)) {
|
||||
Handle<SeqOneByteString> result =
|
||||
isolate->factory()->AllocateRawOneByteInternalizedString(
|
||||
length(), hash_field());
|
||||
length(), raw_hash_field());
|
||||
DisallowHeapAllocation no_gc;
|
||||
CopyChars(result->GetChars(no_gc), string_->GetChars(no_gc) + from_,
|
||||
length());
|
||||
return result;
|
||||
}
|
||||
Handle<SeqTwoByteString> result =
|
||||
isolate->factory()->AllocateRawTwoByteInternalizedString(length(),
|
||||
hash_field());
|
||||
isolate->factory()->AllocateRawTwoByteInternalizedString(
|
||||
length(), raw_hash_field());
|
||||
DisallowHeapAllocation no_gc;
|
||||
CopyChars(result->GetChars(no_gc), string_->GetChars(no_gc) + from_,
|
||||
length());
|
||||
@ -834,7 +834,7 @@ void StringCharacterStream::VisitTwoByteString(const uint16_t* chars,
|
||||
|
||||
bool String::AsArrayIndex(uint32_t* index) {
|
||||
DisallowHeapAllocation no_gc;
|
||||
uint32_t field = hash_field();
|
||||
uint32_t field = raw_hash_field();
|
||||
if (ContainsCachedArrayIndex(field)) {
|
||||
*index = ArrayIndexValueBits::decode(field);
|
||||
return true;
|
||||
@ -846,7 +846,7 @@ bool String::AsArrayIndex(uint32_t* index) {
|
||||
}
|
||||
|
||||
bool String::AsIntegerIndex(size_t* index) {
|
||||
uint32_t field = hash_field();
|
||||
uint32_t field = raw_hash_field();
|
||||
if (ContainsCachedArrayIndex(field)) {
|
||||
*index = ArrayIndexValueBits::decode(field);
|
||||
return true;
|
||||
|
@ -13,15 +13,15 @@
|
||||
namespace v8 {
|
||||
namespace internal {
|
||||
|
||||
StringTableKey::StringTableKey(uint32_t hash_field, int length)
|
||||
: hash_field_(hash_field), length_(length) {}
|
||||
StringTableKey::StringTableKey(uint32_t raw_hash_field, int length)
|
||||
: raw_hash_field_(raw_hash_field), length_(length) {}
|
||||
|
||||
void StringTableKey::set_hash_field(uint32_t hash_field) {
|
||||
hash_field_ = hash_field;
|
||||
void StringTableKey::set_raw_hash_field(uint32_t raw_hash_field) {
|
||||
raw_hash_field_ = raw_hash_field;
|
||||
}
|
||||
|
||||
uint32_t StringTableKey::hash() const {
|
||||
return hash_field_ >> Name::kHashShift;
|
||||
return raw_hash_field_ >> Name::kHashShift;
|
||||
}
|
||||
|
||||
} // namespace internal
|
||||
|
@ -71,7 +71,7 @@ int ComputeStringTableCapacityWithShrink(int current_capacity,
|
||||
|
||||
template <typename StringTableKey>
|
||||
bool KeyIsMatch(StringTableKey* key, String string) {
|
||||
if (string.hash_field() != key->hash_field()) return false;
|
||||
if (string.hash() != key->hash()) return false;
|
||||
if (string.length() != key->length()) return false;
|
||||
return key->IsMatch(string);
|
||||
}
|
||||
@ -355,7 +355,7 @@ class InternalizedStringKey final : public StringTableKey {
|
||||
DCHECK(string->IsFlat());
|
||||
// Make sure hash_field is computed.
|
||||
string->Hash();
|
||||
set_hash_field(string->hash_field());
|
||||
set_raw_hash_field(string->raw_hash_field());
|
||||
}
|
||||
|
||||
bool IsMatch(String string) override { return string_->SlowEquals(string); }
|
||||
@ -383,7 +383,7 @@ class InternalizedStringKey final : public StringTableKey {
|
||||
}
|
||||
// Otherwise allocate a new internalized string.
|
||||
return isolate->factory()->NewInternalizedStringImpl(
|
||||
string_, string_->length(), string_->hash_field());
|
||||
string_, string_->length(), string_->raw_hash_field());
|
||||
}
|
||||
|
||||
private:
|
||||
@ -610,13 +610,14 @@ Address StringTable::Data::TryStringToIndexOrLookupExisting(Isolate* isolate,
|
||||
SequentialStringKey<Char> key(Vector<const Char>(chars, length), seed);
|
||||
|
||||
// String could be an array index.
|
||||
uint32_t hash_field = key.hash_field();
|
||||
uint32_t raw_hash_field = key.raw_hash_field();
|
||||
|
||||
if (Name::ContainsCachedArrayIndex(hash_field)) {
|
||||
return Smi::FromInt(String::ArrayIndexValueBits::decode(hash_field)).ptr();
|
||||
if (Name::ContainsCachedArrayIndex(raw_hash_field)) {
|
||||
return Smi::FromInt(String::ArrayIndexValueBits::decode(raw_hash_field))
|
||||
.ptr();
|
||||
}
|
||||
|
||||
if ((hash_field & Name::kIsNotIntegerIndexMask) == 0) {
|
||||
if ((raw_hash_field & Name::kIsNotIntegerIndexMask) == 0) {
|
||||
// It is an index, but it's not cached.
|
||||
return Smi::FromInt(ResultSentinel::kUnsupported).ptr();
|
||||
}
|
||||
|
@ -20,15 +20,15 @@ namespace internal {
|
||||
class StringTableKey {
|
||||
public:
|
||||
virtual ~StringTableKey() = default;
|
||||
inline StringTableKey(uint32_t hash_field, int length);
|
||||
inline StringTableKey(uint32_t raw_hash_field, int length);
|
||||
|
||||
// The individual keys will have their own AsHandle, we shouldn't call the
|
||||
// base version.
|
||||
Handle<String> AsHandle(Isolate* isolate) = delete;
|
||||
|
||||
uint32_t hash_field() const {
|
||||
DCHECK_NE(0, hash_field_);
|
||||
return hash_field_;
|
||||
uint32_t raw_hash_field() const {
|
||||
DCHECK_NE(0, raw_hash_field_);
|
||||
return raw_hash_field_;
|
||||
}
|
||||
|
||||
virtual bool IsMatch(String string) = 0;
|
||||
@ -36,10 +36,10 @@ class StringTableKey {
|
||||
int length() const { return length_; }
|
||||
|
||||
protected:
|
||||
inline void set_hash_field(uint32_t hash_field);
|
||||
inline void set_raw_hash_field(uint32_t raw_hash_field);
|
||||
|
||||
private:
|
||||
uint32_t hash_field_ = 0;
|
||||
uint32_t raw_hash_field_ = 0;
|
||||
int length_;
|
||||
};
|
||||
|
||||
|
@ -512,13 +512,13 @@ Handle<Object> String::ToNumber(Isolate* isolate, Handle<String> subject) {
|
||||
(len == 1 || data[0] != '0')) {
|
||||
// String hash is not calculated yet but all the data are present.
|
||||
// Update the hash field to speed up sequential convertions.
|
||||
uint32_t hash = StringHasher::MakeArrayIndexHash(d, len);
|
||||
uint32_t raw_hash_field = StringHasher::MakeArrayIndexHash(d, len);
|
||||
#ifdef DEBUG
|
||||
subject->Hash(); // Force hash calculation.
|
||||
DCHECK_EQ(static_cast<int>(subject->hash_field()),
|
||||
static_cast<int>(hash));
|
||||
DCHECK_EQ(static_cast<int>(subject->raw_hash_field()),
|
||||
static_cast<int>(raw_hash_field));
|
||||
#endif
|
||||
subject->set_hash_field(hash);
|
||||
subject->set_raw_hash_field(raw_hash_field);
|
||||
}
|
||||
return handle(Smi::FromInt(d), isolate);
|
||||
}
|
||||
@ -1392,18 +1392,19 @@ uint32_t String::ComputeAndSetHash() {
|
||||
if (string.IsThinString()) {
|
||||
string = ThinString::cast(string).actual();
|
||||
if (length() == string.length()) {
|
||||
set_hash_field(string.hash_field());
|
||||
return hash_field() >> kHashShift;
|
||||
set_raw_hash_field(string.raw_hash_field());
|
||||
return hash();
|
||||
}
|
||||
}
|
||||
uint32_t field = string.IsOneByteRepresentation()
|
||||
? HashString<uint8_t>(string, start, length(), seed)
|
||||
: HashString<uint16_t>(string, start, length(), seed);
|
||||
set_hash_field(field);
|
||||
uint32_t raw_hash_field =
|
||||
string.IsOneByteRepresentation()
|
||||
? HashString<uint8_t>(string, start, length(), seed)
|
||||
: HashString<uint16_t>(string, start, length(), seed);
|
||||
set_raw_hash_field(raw_hash_field);
|
||||
|
||||
// Check the hash code is there.
|
||||
DCHECK(HasHashCode());
|
||||
uint32_t result = field >> kHashShift;
|
||||
uint32_t result = raw_hash_field >> kHashShift;
|
||||
DCHECK_NE(result, 0); // Ensure that the hash value of 0 is never computed.
|
||||
return result;
|
||||
}
|
||||
@ -1413,7 +1414,7 @@ bool String::SlowAsArrayIndex(uint32_t* index) {
|
||||
int length = this->length();
|
||||
if (length <= kMaxCachedArrayIndexLength) {
|
||||
Hash(); // Force computation of hash code.
|
||||
uint32_t field = hash_field();
|
||||
uint32_t field = raw_hash_field();
|
||||
if ((field & kIsNotIntegerIndexMask) != 0) return false;
|
||||
*index = ArrayIndexValueBits::decode(field);
|
||||
return true;
|
||||
@ -1428,7 +1429,7 @@ bool String::SlowAsIntegerIndex(size_t* index) {
|
||||
int length = this->length();
|
||||
if (length <= kMaxCachedArrayIndexLength) {
|
||||
Hash(); // Force computation of hash code.
|
||||
uint32_t field = hash_field();
|
||||
uint32_t field = raw_hash_field();
|
||||
if ((field & kIsNotIntegerIndexMask) != 0) return false;
|
||||
*index = ArrayIndexValueBits::decode(field);
|
||||
return true;
|
||||
|
@ -86,7 +86,7 @@ macro AllocateSeqOneByteString(length: uint32): SeqOneByteString {
|
||||
if (length == 0) return UnsafeCast<SeqOneByteString>(kEmptyString);
|
||||
return new SeqOneByteString{
|
||||
map: kOneByteStringMap,
|
||||
hash_field: kNameEmptyHashField,
|
||||
raw_hash_field: kNameEmptyHashField,
|
||||
length: Signed(length),
|
||||
chars: ...UninitializedIterator {}
|
||||
};
|
||||
@ -98,7 +98,7 @@ macro AllocateSeqTwoByteString(length: uint32): String {
|
||||
if (length == 0) return kEmptyString;
|
||||
return new SeqTwoByteString{
|
||||
map: kStringMap,
|
||||
hash_field: kNameEmptyHashField,
|
||||
raw_hash_field: kNameEmptyHashField,
|
||||
length: Signed(length),
|
||||
chars: ...UninitializedIterator {}
|
||||
};
|
||||
|
@ -108,9 +108,19 @@ const char* StringsStorage::GetConsName(const char* prefix, Name name) {
|
||||
return "";
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
inline uint32_t ComputeStringHash(const char* str, int len) {
|
||||
uint32_t raw_hash_field =
|
||||
StringHasher::HashSequentialString(str, len, kZeroHashSeed);
|
||||
return raw_hash_field >> Name::kHashShift;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
bool StringsStorage::Release(const char* str) {
|
||||
int len = static_cast<int>(strlen(str));
|
||||
uint32_t hash = StringHasher::HashSequentialString(str, len, kZeroHashSeed);
|
||||
uint32_t hash = ComputeStringHash(str, len);
|
||||
base::HashMap::Entry* entry = names_.Lookup(const_cast<char*>(str), hash);
|
||||
DCHECK(entry);
|
||||
if (!entry) {
|
||||
@ -133,7 +143,7 @@ size_t StringsStorage::GetStringCountForTesting() const {
|
||||
}
|
||||
|
||||
base::HashMap::Entry* StringsStorage::GetEntry(const char* str, int len) {
|
||||
uint32_t hash = StringHasher::HashSequentialString(str, len, kZeroHashSeed);
|
||||
uint32_t hash = ComputeStringHash(str, len);
|
||||
return names_.LookupOrInsert(const_cast<char*>(str), hash);
|
||||
}
|
||||
|
||||
|
@ -305,7 +305,7 @@ void Deserializer::LogScriptEvents(Script script) {
|
||||
}
|
||||
|
||||
StringTableInsertionKey::StringTableInsertionKey(Handle<String> string)
|
||||
: StringTableKey(ComputeHashField(*string), string->length()),
|
||||
: StringTableKey(ComputeRawHashField(*string), string->length()),
|
||||
string_(string) {
|
||||
DCHECK(string->IsInternalizedString());
|
||||
}
|
||||
@ -319,10 +319,10 @@ Handle<String> StringTableInsertionKey::AsHandle(Isolate* isolate) {
|
||||
return string_;
|
||||
}
|
||||
|
||||
uint32_t StringTableInsertionKey::ComputeHashField(String string) {
|
||||
// Make sure hash_field() is computed.
|
||||
uint32_t StringTableInsertionKey::ComputeRawHashField(String string) {
|
||||
// Make sure raw_hash_field() is computed.
|
||||
string.Hash();
|
||||
return string.hash_field();
|
||||
return string.raw_hash_field();
|
||||
}
|
||||
|
||||
void Deserializer::PostProcessNewObject(Handle<Map> map, Handle<HeapObject> obj,
|
||||
@ -335,7 +335,7 @@ void Deserializer::PostProcessNewObject(Handle<Map> map, Handle<HeapObject> obj,
|
||||
if (InstanceTypeChecker::IsString(instance_type)) {
|
||||
// Uninitialize hash field as we need to recompute the hash.
|
||||
Handle<String> string = Handle<String>::cast(obj);
|
||||
string->set_hash_field(String::kEmptyHashField);
|
||||
string->set_raw_hash_field(String::kEmptyHashField);
|
||||
// Rehash strings before read-only space is sealed. Strings outside
|
||||
// read-only space are rehashed lazily. (e.g. when rehashing dictionaries)
|
||||
if (space == SnapshotSpace::kReadOnlyHeap) {
|
||||
|
@ -275,7 +275,7 @@ class StringTableInsertionKey final : public StringTableKey {
|
||||
V8_WARN_UNUSED_RESULT Handle<String> AsHandle(LocalIsolate* isolate);
|
||||
|
||||
private:
|
||||
uint32_t ComputeHashField(String string);
|
||||
uint32_t ComputeRawHashField(String string);
|
||||
|
||||
Handle<String> string_;
|
||||
DISALLOW_HEAP_ALLOCATION(no_gc)
|
||||
|
@ -13,6 +13,8 @@ namespace internal {
|
||||
template <typename T>
|
||||
class Vector;
|
||||
|
||||
// Helper class for incrementally calculating string hashes in a form suitable
|
||||
// for storing into Name::raw_hash_field.
|
||||
class V8_EXPORT_PRIVATE StringHasher final {
|
||||
public:
|
||||
StringHasher() = delete;
|
||||
|
@ -214,7 +214,7 @@ TEST(GetObjectProperties) {
|
||||
CHECK(props->type == std::string("v8::internal::SeqOneByteString"));
|
||||
CHECK_EQ(props->num_properties, 4);
|
||||
CheckProp(*props->properties[0], "v8::internal::Map", "map");
|
||||
CheckProp(*props->properties[1], "uint32_t", "hash_field");
|
||||
CheckProp(*props->properties[1], "uint32_t", "raw_hash_field");
|
||||
CheckProp(*props->properties[2], "int32_t", "length", 2);
|
||||
CheckProp(*props->properties[3], "char", "chars",
|
||||
d::PropertyKind::kArrayOfKnownSize, 2);
|
||||
@ -261,7 +261,7 @@ TEST(GetObjectProperties) {
|
||||
}
|
||||
CheckProp(*props2->properties[0], "v8::internal::Map", "map",
|
||||
*reinterpret_cast<i::Tagged_t*>(props->properties[0]->address));
|
||||
CheckProp(*props2->properties[1], "uint32_t", "hash_field",
|
||||
CheckProp(*props2->properties[1], "uint32_t", "raw_hash_field",
|
||||
*reinterpret_cast<int32_t*>(props->properties[1]->address));
|
||||
CheckProp(*props2->properties[2], "int32_t", "length", 2);
|
||||
}
|
||||
@ -276,7 +276,7 @@ TEST(GetObjectProperties) {
|
||||
CHECK_EQ(props2->num_properties, 4);
|
||||
CheckProp(*props2->properties[0], "v8::internal::Map", "map",
|
||||
*reinterpret_cast<i::Tagged_t*>(props->properties[0]->address));
|
||||
CheckProp(*props2->properties[1], "uint32_t", "hash_field",
|
||||
CheckProp(*props2->properties[1], "uint32_t", "raw_hash_field",
|
||||
*reinterpret_cast<i::Tagged_t*>(props->properties[1]->address));
|
||||
CheckProp(*props2->properties[2], "int32_t", "length", 2);
|
||||
|
||||
|
@ -36,7 +36,7 @@ Handle<Name> NewNameWithHash(Isolate* isolate, const char* str, uint32_t hash,
|
||||
}
|
||||
Handle<Name> name = isolate->factory()->NewOneByteInternalizedString(
|
||||
OneByteVector(str), hash_field);
|
||||
name->set_hash_field(hash_field);
|
||||
name->set_raw_hash_field(hash_field);
|
||||
CHECK(name->IsUniqueName());
|
||||
return name;
|
||||
}
|
||||
|
@ -1830,13 +1830,13 @@ void TestString(i::Isolate* isolate, const IndexData& data) {
|
||||
CHECK(s->AsIntegerIndex(&index));
|
||||
CHECK_EQ(data.integer_index, index);
|
||||
s->Hash();
|
||||
CHECK_EQ(0, s->hash_field() & String::kIsNotIntegerIndexMask);
|
||||
CHECK_EQ(0, s->raw_hash_field() & String::kIsNotIntegerIndexMask);
|
||||
CHECK(s->HasHashCode());
|
||||
}
|
||||
if (!s->HasHashCode()) s->Hash();
|
||||
CHECK(s->HasHashCode());
|
||||
if (!data.is_integer_index) {
|
||||
CHECK_NE(0, s->hash_field() & String::kIsNotIntegerIndexMask);
|
||||
CHECK_NE(0, s->raw_hash_field() & String::kIsNotIntegerIndexMask);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -378,10 +378,11 @@ void CompileRunAndVerify(FuzzerArgs* args, const std::string& source) {
|
||||
}
|
||||
|
||||
if (!ResultsAreIdentical(args)) {
|
||||
uint32_t hash = StringHasher::HashSequentialString(
|
||||
uint32_t raw_hash_field = StringHasher::HashSequentialString(
|
||||
args->input_data, static_cast<int>(args->input_length),
|
||||
kRegExpBuiltinsFuzzerHashSeed);
|
||||
FATAL("!ResultAreIdentical(args); RegExpBuiltinsFuzzerHash=%x", hash);
|
||||
FATAL("!ResultAreIdentical(args); RegExpBuiltinsFuzzerHash=%x",
|
||||
raw_hash_field);
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user