Commit 93cd816c authored by caitpotter88's avatar caitpotter88 Committed by Commit bot

Make TemplateLiteral hashing algorithm more memory efficient

Previously, a separate string to be hashed (in order to help determine the need to
use a cached Template Call Site) was built up by joining UTF8 spans within a template.

Now, the hash key is generated from the original spans, removing the need to allocate a new
buffer and copy bytes into it.

BUG=

Review URL: https://codereview.chromium.org/765473006

Cr-Commit-Position: refs/heads/master@{#25549}
parent 5081f4cc
...@@ -6736,6 +6736,30 @@ uint32_t StringHasher::GetHashCore(uint32_t running_hash) { ...@@ -6736,6 +6736,30 @@ uint32_t StringHasher::GetHashCore(uint32_t running_hash) {
} }
uint32_t StringHasher::ComputeRunningHash(uint32_t running_hash,
const uc16* chars, int length) {
DCHECK_NOT_NULL(chars);
DCHECK(length >= 0);
for (int i = 0; i < length; ++i) {
running_hash = AddCharacterCore(running_hash, *chars++);
}
return running_hash;
}
uint32_t StringHasher::ComputeRunningHashOneByte(uint32_t running_hash,
const char* chars,
int length) {
DCHECK_NOT_NULL(chars);
DCHECK(length >= 0);
for (int i = 0; i < length; ++i) {
uint16_t c = static_cast<uint16_t>(*chars++);
running_hash = AddCharacterCore(running_hash, c);
}
return running_hash;
}
void StringHasher::AddCharacter(uint16_t c) { void StringHasher::AddCharacter(uint16_t c) {
// Use the Jenkins one-at-a-time hash function to update the hash // Use the Jenkins one-at-a-time hash function to update the hash
// for the given character. // for the given character.
......
...@@ -8493,6 +8493,11 @@ class StringHasher { ...@@ -8493,6 +8493,11 @@ class StringHasher {
// Reusable parts of the hashing algorithm. // Reusable parts of the hashing algorithm.
INLINE(static uint32_t AddCharacterCore(uint32_t running_hash, uint16_t c)); INLINE(static uint32_t AddCharacterCore(uint32_t running_hash, uint16_t c));
INLINE(static uint32_t GetHashCore(uint32_t running_hash)); INLINE(static uint32_t GetHashCore(uint32_t running_hash));
INLINE(static uint32_t ComputeRunningHash(uint32_t running_hash,
const uc16* chars, int length));
INLINE(static uint32_t ComputeRunningHashOneByte(uint32_t running_hash,
const char* chars,
int length));
protected: protected:
// Returns the value to store in the hash field of a string with // Returns the value to store in the hash field of a string with
......
...@@ -5295,14 +5295,7 @@ ZoneList<Expression*>* Parser::TemplateRawStrings(const TemplateLiteral* lit, ...@@ -5295,14 +5295,7 @@ ZoneList<Expression*>* Parser::TemplateRawStrings(const TemplateLiteral* lit,
raw_strings = new (zone()) ZoneList<Expression*>(total, zone()); raw_strings = new (zone()) ZoneList<Expression*>(total, zone());
int num_hash_chars = (total - 1) * 3; uint32_t running_hash = 0;
for (int index = 0; index < total; ++index) {
// Allow about length * 4 to handle most UTF8 sequences.
num_hash_chars += lengths->at(index) * 4;
}
Vector<uint8_t> hash_string = Vector<uint8_t>::New(num_hash_chars);
num_hash_chars = 0;
for (int index = 0; index < total; ++index) { for (int index = 0; index < total; ++index) {
int span_start = cooked_strings->at(index)->position() + 1; int span_start = cooked_strings->at(index)->position() + 1;
...@@ -5311,9 +5304,8 @@ ZoneList<Expression*>* Parser::TemplateRawStrings(const TemplateLiteral* lit, ...@@ -5311,9 +5304,8 @@ ZoneList<Expression*>* Parser::TemplateRawStrings(const TemplateLiteral* lit,
int to_index = 0; int to_index = 0;
if (index) { if (index) {
hash_string[num_hash_chars++] = '$'; running_hash = StringHasher::ComputeRunningHashOneByte(
hash_string[num_hash_chars++] = '{'; running_hash, "${}", 3);
hash_string[num_hash_chars++] = '}';
} }
SmartArrayPointer<char> raw_chars = SmartArrayPointer<char> raw_chars =
...@@ -5330,7 +5322,6 @@ ZoneList<Expression*>* Parser::TemplateRawStrings(const TemplateLiteral* lit, ...@@ -5330,7 +5322,6 @@ ZoneList<Expression*>* Parser::TemplateRawStrings(const TemplateLiteral* lit,
++from_index; ++from_index;
} }
} }
hash_string[num_hash_chars++] = ch;
raw_chars[to_index++] = ch; raw_chars[to_index++] = ch;
} }
...@@ -5342,6 +5333,8 @@ ZoneList<Expression*>* Parser::TemplateRawStrings(const TemplateLiteral* lit, ...@@ -5342,6 +5333,8 @@ ZoneList<Expression*>* Parser::TemplateRawStrings(const TemplateLiteral* lit,
if (utf16_length > 0) { if (utf16_length > 0) {
uc16* utf16_buffer = zone()->NewArray<uc16>(utf16_length); uc16* utf16_buffer = zone()->NewArray<uc16>(utf16_length);
to_index = decoder->WriteUtf16(utf16_buffer, utf16_length); to_index = decoder->WriteUtf16(utf16_buffer, utf16_length);
running_hash = StringHasher::ComputeRunningHash(
running_hash, utf16_buffer, to_index);
const uint16_t* data = reinterpret_cast<const uint16_t*>(utf16_buffer); const uint16_t* data = reinterpret_cast<const uint16_t*>(utf16_buffer);
const AstRawString* raw_str = ast_value_factory()->GetTwoByteString( const AstRawString* raw_str = ast_value_factory()->GetTwoByteString(
Vector<const uint16_t>(data, to_index)); Vector<const uint16_t>(data, to_index));
...@@ -5354,11 +5347,10 @@ ZoneList<Expression*>* Parser::TemplateRawStrings(const TemplateLiteral* lit, ...@@ -5354,11 +5347,10 @@ ZoneList<Expression*>* Parser::TemplateRawStrings(const TemplateLiteral* lit,
raw_strings->Add(raw_lit, zone()); raw_strings->Add(raw_lit, zone());
} }
hash_string.Truncate(num_hash_chars); // Hash key is used exclusively by template call site caching. There are no
int utf16_length; // real security implications for unseeded hashes, and no issues with changing
*hash = StringHasher::ComputeUtf8Hash(Vector<const char>::cast(hash_string), // the hashing algorithm to improve performance or entropy.
num_hash_chars, &utf16_length); *hash = running_hash;
hash_string.Dispose();
return raw_strings; return raw_strings;
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment