OLD | NEW |
---|---|
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 Loading... | |
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 |
OLD | NEW |