Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(501)

Side by Side Diff: src/parser.cc

Issue 742643003: Cache template literal callSiteObj (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Created 6 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2012 the V8 project authors. All rights reserved. 1 // Copyright 2012 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "src/v8.h" 5 #include "src/v8.h"
6 6
7 #include "src/api.h" 7 #include "src/api.h"
8 #include "src/ast.h" 8 #include "src/ast.h"
9 #include "src/bailout-reason.h" 9 #include "src/bailout-reason.h"
10 #include "src/base/platform/platform.h" 10 #include "src/base/platform/platform.h"
(...skipping 5196 matching lines...) Expand 10 before | Expand all | Expand 10 after
5207 Token::ADD, cooked_str, expressions->at(i), 5207 Token::ADD, cooked_str, expressions->at(i),
5208 cooked_str->position()), 5208 cooked_str->position()),
5209 cooked_str->position()); 5209 cooked_str->position());
5210 } 5210 }
5211 cooked_str = cooked_strings->at(i); 5211 cooked_str = cooked_strings->at(i);
5212 expr = factory()->NewBinaryOperation(Token::ADD, expr, cooked_str, 5212 expr = factory()->NewBinaryOperation(Token::ADD, expr, cooked_str,
5213 cooked_str->position()); 5213 cooked_str->position());
5214 } 5214 }
5215 return expr; 5215 return expr;
5216 } else { 5216 } else {
5217 ZoneList<Expression*>* raw_strings = TemplateRawStrings(lit); 5217 uint32_t hash;
5218 ZoneList<Expression*>* raw_strings = TemplateRawStrings(lit, &hash);
5218 Handle<String> source(String::cast(script()->source())); 5219 Handle<String> source(String::cast(script()->source()));
5219 5220
5220 int cooked_idx = function_state_->NextMaterializedLiteralIndex(); 5221 int cooked_idx = function_state_->NextMaterializedLiteralIndex();
5221 int raw_idx = function_state_->NextMaterializedLiteralIndex(); 5222 int raw_idx = function_state_->NextMaterializedLiteralIndex();
5222 5223
5223 // GetTemplateCallSite 5224 // GetTemplateCallSite
5224 ZoneList<Expression*>* args = new (zone()) ZoneList<Expression*>(4, zone()); 5225 ZoneList<Expression*>* args = new (zone()) ZoneList<Expression*>(4, zone());
5225 args->Add(factory()->NewArrayLiteral( 5226 args->Add(factory()->NewArrayLiteral(
5226 const_cast<ZoneList<Expression*>*>(cooked_strings), 5227 const_cast<ZoneList<Expression*>*>(cooked_strings),
5227 cooked_idx, pos), 5228 cooked_idx, pos),
5228 zone()); 5229 zone());
5229 args->Add( 5230 args->Add(
5230 factory()->NewArrayLiteral( 5231 factory()->NewArrayLiteral(
5231 const_cast<ZoneList<Expression*>*>(raw_strings), raw_idx, pos), 5232 const_cast<ZoneList<Expression*>*>(raw_strings), raw_idx, pos),
5232 zone()); 5233 zone());
5234 args->Add(factory()->NewSmiLiteral(hash, pos), zone());
5233 this->CheckPossibleEvalCall(tag, scope_); 5235 this->CheckPossibleEvalCall(tag, scope_);
5234 Expression* call_site = factory()->NewCallRuntime( 5236 Expression* call_site = factory()->NewCallRuntime(
5235 ast_value_factory()->get_template_callsite_string(), NULL, args, start); 5237 ast_value_factory()->get_template_callsite_string(), NULL, args, start);
5236 5238
5237 // Call TagFn 5239 // Call TagFn
5238 ZoneList<Expression*>* call_args = 5240 ZoneList<Expression*>* call_args =
5239 new (zone()) ZoneList<Expression*>(expressions->length() + 1, zone()); 5241 new (zone()) ZoneList<Expression*>(expressions->length() + 1, zone());
5240 call_args->Add(call_site, zone()); 5242 call_args->Add(call_site, zone());
5241 call_args->AddAll(*expressions, zone()); 5243 call_args->AddAll(*expressions, zone());
5242 return factory()->NewCall(tag, call_args, pos); 5244 return factory()->NewCall(tag, call_args, pos);
5243 } 5245 }
5244 } 5246 }
5245 5247
5246 5248
5247 ZoneList<Expression*>* Parser::TemplateRawStrings(const TemplateLiteral* lit) { 5249 // MurmurHash (Public Domain)
5250 // TODO(caitp): use std::hash if available?
5251 static uint32_t MurmurHash(Vector<uint8_t> chars, int length) {
5252 // TODO(caitp): Do we want to seed this to improve randomness? I'm not sure
5253 // it matters.
5254 uint32_t hash = 0;
5255
5256 Vector<const uint32_t> chunks = Vector<const uint32_t>::cast(chars);
5257 int num_chunks = chunks.length();
5258
5259 // MurmurHash magic numbers
5260 static const uint32_t c1 = 0xcc9e2d51;
5261 static const uint32_t c2 = 0x1b873593;
5262 static const uint32_t r1 = 15;
5263 static const uint32_t r2 = 13;
5264 static const uint32_t m = 5;
5265 static const uint32_t n = 0xe6546b64;
5266 static const uint32_t f1 = 0x85ebca6b;
5267 static const uint32_t f2 = 0xc2b2ae35;
5268
5269 for (int i = 0; i < num_chunks; ++i) {
5270 uint32_t k = chunks[i];
5271
5272 k *= c1;
5273 k = (k << r1) | (k >> (32 - r1));
5274 k *= c2;
5275
5276 hash ^= k;
5277 hash = ((hash << r2) | (hash >> (32 - r2))) * m + n;
5278 }
5279
5280 const uint8_t *tail = chars.start() + num_chunks * 4;
5281 uint32_t k1 = 0;
5282
5283 switch (length & 3) {
5284 case 3:
5285 k1 ^= tail[2] << 16;
5286 case 2:
5287 k1 ^= tail[1] << 8;
5288 case 1:
5289 k1 ^= tail[0];
5290 k1 *= c1;
5291 k1 = (k1 << r1) | (k1 >> (32 - r1));
5292 k1 *= c2;
5293 hash ^= k1;
5294 }
5295
5296 hash ^= length;
5297 hash ^= (hash >> 16);
5298 hash *= f1;
5299 hash ^= (hash >> 13);
5300 hash *= f2;
5301 hash ^= (hash >> 16);
5302
5303 return hash;
5304 }
5305
5306
5307 ZoneList<Expression*>* Parser::TemplateRawStrings(const TemplateLiteral* lit,
5308 uint32_t* hash) {
5248 const ZoneList<int>* lengths = lit->lengths(); 5309 const ZoneList<int>* lengths = lit->lengths();
5249 const ZoneList<Expression*>* cooked_strings = lit->cooked(); 5310 const ZoneList<Expression*>* cooked_strings = lit->cooked();
5250 int total = lengths->length(); 5311 int total = lengths->length();
5251 ZoneList<Expression*>* raw_strings; 5312 ZoneList<Expression*>* raw_strings;
5252 5313
5253 // Given a TemplateLiteral, produce a list of raw strings, used for generating 5314 // Given a TemplateLiteral, produce a list of raw strings, used for generating
5254 // a CallSite object for a tagged template invocations. 5315 // a CallSite object for a tagged template invocations.
5255 // 5316 //
5256 // A raw string will consist of the unescaped characters of a template span, 5317 // A raw string will consist of the unescaped characters of a template span,
5257 // with end-of-line sequences normalized to U+000A LINE FEEDs, and without 5318 // with end-of-line sequences normalized to U+000A LINE FEEDs, and without
5258 // leading or trailing template delimiters. 5319 // leading or trailing template delimiters.
5259 // 5320 //
5260 5321
5261 DCHECK(total); 5322 DCHECK(total);
5262 5323
5263 Handle<String> source(String::cast(script()->source())); 5324 Handle<String> source(String::cast(script()->source()));
5264 5325
5265 raw_strings = new (zone()) ZoneList<Expression*>(total, zone()); 5326 raw_strings = new (zone()) ZoneList<Expression*>(total, zone());
5266 5327
5328 int num_dummy_chars = (total - 1) * 4;
5329 for (int index = 0; index < total; ++index) {
5330 num_dummy_chars += lengths->at(index);
5331 }
5332
5333 Vector<uint8_t> hash_string = Vector<uint8_t>::New(num_dummy_chars);
arv (Not doing code reviews) 2014/11/19 06:09:11 What about two byte strings? Can we use StringHas
caitp (gmail) 2014/11/19 07:15:05 String::ToCString claims to return a UTF8 represen
5334 num_dummy_chars = 0;
5335
5267 for (int index = 0; index < total; ++index) { 5336 for (int index = 0; index < total; ++index) {
5268 int span_start = cooked_strings->at(index)->position() + 1; 5337 int span_start = cooked_strings->at(index)->position() + 1;
5269 int span_end = lengths->at(index) - 1; 5338 int span_end = lengths->at(index) - 1;
5270 int length; 5339 int length;
5271 int to_index = 0; 5340 int to_index = 0;
5272 5341
5342 if (index) {
5343 hash_string[num_dummy_chars++] = '$';
5344 hash_string[num_dummy_chars++] = '{';
5345 hash_string[num_dummy_chars++] = '.';
5346 hash_string[num_dummy_chars++] = '}';
5347 }
5348
5273 SmartArrayPointer<char> raw_chars = 5349 SmartArrayPointer<char> raw_chars =
5274 source->ToCString(ALLOW_NULLS, FAST_STRING_TRAVERSAL, span_start, 5350 source->ToCString(ALLOW_NULLS, FAST_STRING_TRAVERSAL, span_start,
5275 span_end, &length); 5351 span_end, &length);
5276 5352
5277 // Normalize raw line-feeds. [U+000D U+000A] (CRLF) and [U+000D] (CR) must 5353 // Normalize raw line-feeds. [U+000D U+000A] (CRLF) and [U+000D] (CR) must
5278 // be translated into U+000A (LF). 5354 // be translated into U+000A (LF).
5279 for (int from_index = 0; from_index < length; ++from_index) { 5355 for (int from_index = 0; from_index < length; ++from_index) {
5280 char ch = raw_chars[from_index]; 5356 char ch = raw_chars[from_index];
5281 if (ch == '\r') { 5357 if (ch == '\r') {
5282 ch = '\n'; 5358 ch = '\n';
5283 if (from_index + 1 < length && raw_chars[from_index + 1] == '\n') { 5359 if (from_index + 1 < length && raw_chars[from_index + 1] == '\n') {
5284 ++from_index; 5360 ++from_index;
5285 } 5361 }
5286 } 5362 }
5363 hash_string[num_dummy_chars++] = ch;
5287 raw_chars[to_index++] = ch; 5364 raw_chars[to_index++] = ch;
5288 } 5365 }
5289 5366
5290 const AstRawString* raw_str = ast_value_factory()->GetOneByteString( 5367 const AstRawString* raw_str = ast_value_factory()->GetOneByteString(
5291 OneByteVector(raw_chars.get(), to_index)); 5368 OneByteVector(raw_chars.get(), to_index));
5292 Literal* raw_lit = factory()->NewStringLiteral(raw_str, span_start - 1); 5369 Literal* raw_lit = factory()->NewStringLiteral(raw_str, span_start - 1);
5293 raw_strings->Add(raw_lit, zone()); 5370 raw_strings->Add(raw_lit, zone());
5294 } 5371 }
5295 5372
5373 *hash = MurmurHash(hash_string, num_dummy_chars);
5374 hash_string.Dispose();
5375
5296 return raw_strings; 5376 return raw_strings;
5297 } 5377 }
5298 } } // namespace v8::internal 5378 } } // namespace v8::internal
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698