| Index: src/parser.cc | 
| diff --git a/src/parser.cc b/src/parser.cc | 
| index 6fcca2070bf27b7e8d8b95147a5a7b39c77ac696..057b2e9eb2ef961bf296657ecfe5f25b4c9400a9 100644 | 
| --- a/src/parser.cc | 
| +++ b/src/parser.cc | 
| @@ -5186,8 +5186,10 @@ void Parser::AddTemplateSpan(TemplateLiteralState* state, bool tail) { | 
| int pos = scanner()->location().beg_pos; | 
| int end = scanner()->location().end_pos - (tail ? 1 : 2); | 
| const AstRawString* tv = scanner()->CurrentSymbol(ast_value_factory()); | 
| +  const AstRawString* trv = scanner()->CurrentRawSymbol(ast_value_factory()); | 
| Literal* cooked = factory()->NewStringLiteral(tv, pos); | 
| -  (*state)->AddTemplateSpan(cooked, end, zone()); | 
| +  Literal* raw = factory()->NewStringLiteral(trv, pos); | 
| +  (*state)->AddTemplateSpan(cooked, raw, end, zone()); | 
| } | 
|  | 
|  | 
| @@ -5202,8 +5204,10 @@ Expression* Parser::CloseTemplateLiteral(TemplateLiteralState* state, int start, | 
| TemplateLiteral* lit = *state; | 
| int pos = lit->position(); | 
| const ZoneList<Expression*>* cooked_strings = lit->cooked(); | 
| +  const ZoneList<Expression*>* raw_strings = lit->raw(); | 
| const ZoneList<Expression*>* expressions = lit->expressions(); | 
| -  CHECK(cooked_strings->length() == (expressions->length() + 1)); | 
| +  DCHECK_EQ(cooked_strings->length(), raw_strings->length()); | 
| +  DCHECK_EQ(cooked_strings->length(), expressions->length() + 1); | 
|  | 
| if (!tag) { | 
| // Build tree of BinaryOps to simplify code-generation | 
| @@ -5231,9 +5235,7 @@ Expression* Parser::CloseTemplateLiteral(TemplateLiteralState* state, int start, | 
| } | 
| return expr; | 
| } else { | 
| -    uint32_t hash; | 
| -    ZoneList<Expression*>* raw_strings = TemplateRawStrings(lit, &hash); | 
| -    Handle<String> source(String::cast(script()->source())); | 
| +    uint32_t hash = ComputeTemplateLiteralHash(lit); | 
|  | 
| int cooked_idx = function_state_->NextMaterializedLiteralIndex(); | 
| int raw_idx = function_state_->NextMaterializedLiteralIndex(); | 
| @@ -5249,7 +5251,7 @@ Expression* Parser::CloseTemplateLiteral(TemplateLiteralState* state, int start, | 
| const_cast<ZoneList<Expression*>*>(raw_strings), raw_idx, pos), | 
| zone()); | 
|  | 
| -    // Ensure hash is suitable as an Smi value | 
| +    // Ensure hash is suitable as a Smi value | 
| Smi* hash_obj = Smi::cast(Internals::IntToSmi(static_cast<int>(hash))); | 
| args->Add(factory()->NewSmiLiteral(hash_obj->value(), pos), zone()); | 
|  | 
| @@ -5267,84 +5269,32 @@ Expression* Parser::CloseTemplateLiteral(TemplateLiteralState* state, int start, | 
| } | 
|  | 
|  | 
| -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(); | 
| -  ZoneList<Expression*>* raw_strings; | 
| - | 
| -  // Given a TemplateLiteral, produce a list of raw strings, used for generating | 
| -  // a CallSite object for a tagged template invocations. | 
| -  // | 
| -  // A raw string will consist of the unescaped characters of a template span, | 
| -  // with end-of-line sequences normalized to U+000A LINE FEEDs, and without | 
| -  // leading or trailing template delimiters. | 
| -  // | 
| - | 
| +uint32_t Parser::ComputeTemplateLiteralHash(const TemplateLiteral* lit) { | 
| +  const ZoneList<Expression*>* raw_strings = lit->raw(); | 
| +  int total = raw_strings->length(); | 
| DCHECK(total); | 
|  | 
| -  Handle<String> source(String::cast(script()->source())); | 
| - | 
| -  raw_strings = new (zone()) ZoneList<Expression*>(total, zone()); | 
| - | 
| uint32_t running_hash = 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; | 
| - | 
| if (index) { | 
| running_hash = StringHasher::ComputeRunningHashOneByte( | 
| running_hash, "${}", 3); | 
| } | 
|  | 
| -    SmartArrayPointer<char> raw_chars = | 
| -        source->ToCString(ALLOW_NULLS, FAST_STRING_TRAVERSAL, span_start, | 
| -                          span_end, &length); | 
| - | 
| -    // Normalize raw line-feeds. [U+000D U+000A] (CRLF) and [U+000D] (CR) must | 
| -    // be translated into U+000A (LF). | 
| -    for (int from_index = 0; from_index < length; ++from_index) { | 
| -      char ch = raw_chars[from_index]; | 
| -      if (ch == '\r') { | 
| -        ch = '\n'; | 
| -        if (from_index + 1 < length && raw_chars[from_index + 1] == '\n') { | 
| -          ++from_index; | 
| -        } | 
| -      } | 
| -      raw_chars[to_index++] = ch; | 
| -    } | 
| - | 
| -    Access<UnicodeCache::Utf8Decoder> | 
| -        decoder(isolate()->unicode_cache()->utf8_decoder()); | 
| -    decoder->Reset(raw_chars.get(), to_index); | 
| -    int utf16_length = decoder->Utf16Length(); | 
| -    Literal* raw_lit = NULL; | 
| -    if (utf16_length > 0) { | 
| -      uc16* utf16_buffer = zone()->NewArray<uc16>(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 AstRawString* raw_str = ast_value_factory()->GetTwoByteString( | 
| -          Vector<const uint16_t>(data, to_index)); | 
| -      raw_lit = factory()->NewStringLiteral(raw_str, span_start - 1); | 
| +    const AstRawString* raw_string = | 
| +        raw_strings->at(index)->AsLiteral()->raw_value()->AsString(); | 
| +    if (raw_string->is_one_byte()) { | 
| +      const char* data = reinterpret_cast<const char*>(raw_string->raw_data()); | 
| +      running_hash = StringHasher::ComputeRunningHashOneByte( | 
| +          running_hash, data, raw_string->length()); | 
| } else { | 
| -      raw_lit = factory()->NewStringLiteral( | 
| -          ast_value_factory()->empty_string(), span_start - 1); | 
| +      const uc16* data = reinterpret_cast<const uc16*>(raw_string->raw_data()); | 
| +      running_hash = StringHasher::ComputeRunningHash(running_hash, data, | 
| +                                                      raw_string->length()); | 
| } | 
| -    DCHECK_NOT_NULL(raw_lit); | 
| -    raw_strings->Add(raw_lit, zone()); | 
| } | 
|  | 
| -  // Hash key is used exclusively by template call site caching. There are no | 
| -  // real security implications for unseeded hashes, and no issues with changing | 
| -  // the hashing algorithm to improve performance or entropy. | 
| -  *hash = running_hash; | 
| - | 
| -  return raw_strings; | 
| +  return running_hash; | 
| } | 
| } }  // namespace v8::internal | 
|  |