Chromium Code Reviews| Index: src/parser.cc |
| diff --git a/src/parser.cc b/src/parser.cc |
| index 5e7530496bdbcac537a066c30598b21c9c9b9bb4..bb637ee428aa8b6c2a9308b1f2939d15985377a0 100644 |
| --- a/src/parser.cc |
| +++ b/src/parser.cc |
| @@ -5231,7 +5231,8 @@ Expression* Parser::CloseTemplateLiteral(TemplateLiteralState* state, int start, |
| } |
| return expr; |
| } else { |
| - ZoneList<Expression*>* raw_strings = TemplateRawStrings(lit); |
| + uint32_t hash; |
| + ZoneList<Expression*>* raw_strings = TemplateRawStrings(lit, &hash); |
| Handle<String> source(String::cast(script()->source())); |
| int cooked_idx = function_state_->NextMaterializedLiteralIndex(); |
| @@ -5247,6 +5248,7 @@ Expression* Parser::CloseTemplateLiteral(TemplateLiteralState* state, int start, |
| factory()->NewArrayLiteral( |
| const_cast<ZoneList<Expression*>*>(raw_strings), raw_idx, pos), |
| zone()); |
| + args->Add(factory()->NewSmiLiteral(hash, pos), zone()); |
| this->CheckPossibleEvalCall(tag, scope_); |
| Expression* call_site = factory()->NewCallRuntime( |
| ast_value_factory()->get_template_callsite_string(), NULL, args, start); |
| @@ -5261,7 +5263,8 @@ Expression* Parser::CloseTemplateLiteral(TemplateLiteralState* state, int start, |
| } |
| -ZoneList<Expression*>* Parser::TemplateRawStrings(const TemplateLiteral* lit) { |
| +ZoneList<Expression*>* Parser::TemplateRawStrings(const TemplateLiteral* lit, |
| + uint32_t* hash) { |
| const ZoneList<int>* lengths = lit->lengths(); |
| const ZoneList<Expression*>* cooked_strings = lit->cooked(); |
| int total = lengths->length(); |
| @@ -5281,11 +5284,32 @@ ZoneList<Expression*>* Parser::TemplateRawStrings(const TemplateLiteral* lit) { |
| raw_strings = new (zone()) ZoneList<Expression*>(total, zone()); |
| + int num_hash_chars = (total - 1) * 4; |
| + for (int index = 0; index < total; ++index) { |
| + // Accomodate multi-byte UTF8 characters without re-allocating |
| + num_hash_chars += (lengths->at(index) * 5); |
| + } |
| + |
| + // Construct a single string to calculate a hash from, joined by a sequence |
| + // which cannot be constructed using escape sequences. |
| + Vector<uint8_t> hash_string = Vector<uint8_t>::New(num_hash_chars); |
| + num_hash_chars = 0; |
| + |
| for (int index = 0; index < total; ++index) { |
| int span_start = cooked_strings->at(index)->position() + 1; |
| int span_end = lengths->at(index) - 1; |
| int length; |
| int to_index = 0; |
| + bool has_multibyte = false; |
| + |
| + if (index) { |
| + // Separate raw string elements by sequence which cannot otherwise be |
| + // encountered. |
| + hash_string[num_hash_chars++] = '$'; |
| + hash_string[num_hash_chars++] = '{'; |
| + hash_string[num_hash_chars++] = '.'; |
|
arv (Not doing code reviews)
2014/11/19 21:29:04
Can we skip the '.' here?
|
| + hash_string[num_hash_chars++] = '}'; |
| + } |
| SmartArrayPointer<char> raw_chars = |
| source->ToCString(ALLOW_NULLS, FAST_STRING_TRAVERSAL, span_start, |
|
arv (Not doing code reviews)
2014/11/19 21:29:04
I still think this is suspicious. The scanner know
|
| @@ -5301,15 +5325,37 @@ ZoneList<Expression*>* Parser::TemplateRawStrings(const TemplateLiteral* lit) { |
| ++from_index; |
| } |
| } |
| + if (ch & 0x80) has_multibyte = true; |
| + hash_string[num_hash_chars++] = ch; |
| raw_chars[to_index++] = ch; |
| } |
| - const AstRawString* raw_str = ast_value_factory()->GetOneByteString( |
| - OneByteVector(raw_chars.get(), to_index)); |
| - Literal* raw_lit = factory()->NewStringLiteral(raw_str, span_start - 1); |
| - raw_strings->Add(raw_lit, zone()); |
| + if (has_multibyte) { |
| + // Convert to UTF16 --- One-byte AstRawStrings do not seem to be |
|
arv (Not doing code reviews)
2014/11/19 21:29:04
one byte is used for ascii
|
| + // decoded from UTF8. |
| + unibrow::Utf8Decoder<256> decoder(raw_chars.get(), to_index); |
|
caitp (gmail)
2014/11/19 20:16:54
A better solution for this is probably to make sur
arv (Not doing code reviews)
2014/11/19 21:29:04
We have code in the scanner for handling this alre
|
| + uc16* buffer = zone()->NewArray<uc16>(to_index); |
| + int utf16_length = decoder.WriteUtf16(buffer, to_index); |
| + |
| + const AstRawString* raw_str = ast_value_factory()->GetTwoByteString( |
| + Vector<const uint16_t>(reinterpret_cast<const uint16_t*>(buffer), |
| + utf16_length)); |
| + Literal* raw_lit = factory()->NewStringLiteral(raw_str, span_start - 1); |
| + raw_strings->Add(raw_lit, zone()); |
| + } else { |
| + const AstRawString* raw_str = ast_value_factory()->GetOneByteString( |
| + OneByteVector(raw_chars.get(), to_index)); |
| + Literal* raw_lit = factory()->NewStringLiteral(raw_str, span_start - 1); |
| + raw_strings->Add(raw_lit, zone()); |
| + } |
| } |
| + int utf16_length; |
| + hash_string.Truncate(num_hash_chars); |
| + *hash = StringHasher::ComputeUtf8Hash(Vector<const char>::cast(hash_string), |
| + /* seed */ 0, &utf16_length); |
| + hash_string.Dispose(); |
| + |
| return raw_strings; |
| } |
| } } // namespace v8::internal |