OLD | NEW |
1 // Copyright 2010 the V8 project authors. All rights reserved. | 1 // Copyright 2010 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 338 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
349 if (result.is_null()) { | 349 if (result.is_null()) { |
350 result = Factory::LookupSymbol(string); | 350 result = Factory::LookupSymbol(string); |
351 symbol_cache_.at(symbol_id) = result; | 351 symbol_cache_.at(symbol_id) = result; |
352 return result; | 352 return result; |
353 } | 353 } |
354 Counters::total_preparse_symbols_skipped.Increment(); | 354 Counters::total_preparse_symbols_skipped.Increment(); |
355 return result; | 355 return result; |
356 } | 356 } |
357 | 357 |
358 | 358 |
359 Vector<unsigned> PartialParserRecorder::ExtractData() { | |
360 int function_size = function_store_.size(); | |
361 int total_size = ScriptDataImpl::kHeaderSize + function_size; | |
362 Vector<unsigned> data = Vector<unsigned>::New(total_size); | |
363 preamble_[ScriptDataImpl::kFunctionsSizeOffset] = function_size; | |
364 preamble_[ScriptDataImpl::kSymbolCountOffset] = 0; | |
365 memcpy(data.start(), preamble_, sizeof(preamble_)); | |
366 int symbol_start = ScriptDataImpl::kHeaderSize + function_size; | |
367 if (function_size > 0) { | |
368 function_store_.WriteTo(data.SubVector(ScriptDataImpl::kHeaderSize, | |
369 symbol_start)); | |
370 } | |
371 return data; | |
372 } | |
373 | |
374 | |
375 void CompleteParserRecorder::LogSymbol(int start, Vector<const char> literal) { | |
376 if (!is_recording_) return; | |
377 | |
378 int hash = vector_hash(literal); | |
379 HashMap::Entry* entry = symbol_table_.Lookup(&literal, hash, true); | |
380 int id = static_cast<int>(reinterpret_cast<intptr_t>(entry->value)); | |
381 if (id == 0) { | |
382 // Put (symbol_id_ + 1) into entry and increment it. | |
383 id = ++symbol_id_; | |
384 entry->value = reinterpret_cast<void*>(id); | |
385 Vector<Vector<const char> > symbol = symbol_entries_.AddBlock(1, literal); | |
386 entry->key = &symbol[0]; | |
387 } | |
388 WriteNumber(id - 1); | |
389 } | |
390 | |
391 | |
392 Vector<unsigned> CompleteParserRecorder::ExtractData() { | |
393 int function_size = function_store_.size(); | |
394 // Add terminator to symbols, then pad to unsigned size. | |
395 int symbol_size = symbol_store_.size(); | |
396 int padding = sizeof(unsigned) - (symbol_size % sizeof(unsigned)); | |
397 symbol_store_.AddBlock(padding, ScriptDataImpl::kNumberTerminator); | |
398 symbol_size += padding; | |
399 int total_size = ScriptDataImpl::kHeaderSize + function_size | |
400 + (symbol_size / sizeof(unsigned)); | |
401 Vector<unsigned> data = Vector<unsigned>::New(total_size); | |
402 preamble_[ScriptDataImpl::kFunctionsSizeOffset] = function_size; | |
403 preamble_[ScriptDataImpl::kSymbolCountOffset] = symbol_id_; | |
404 memcpy(data.start(), preamble_, sizeof(preamble_)); | |
405 int symbol_start = ScriptDataImpl::kHeaderSize + function_size; | |
406 if (function_size > 0) { | |
407 function_store_.WriteTo(data.SubVector(ScriptDataImpl::kHeaderSize, | |
408 symbol_start)); | |
409 } | |
410 if (!has_error()) { | |
411 symbol_store_.WriteTo( | |
412 Vector<byte>::cast(data.SubVector(symbol_start, total_size))); | |
413 } | |
414 return data; | |
415 } | |
416 | |
417 | |
418 FunctionEntry ScriptDataImpl::GetFunctionEntry(int start) { | 359 FunctionEntry ScriptDataImpl::GetFunctionEntry(int start) { |
419 // The current pre-data entry must be a FunctionEntry with the given | 360 // The current pre-data entry must be a FunctionEntry with the given |
420 // start position. | 361 // start position. |
421 if ((function_index_ + FunctionEntry::kSize <= store_.length()) | 362 if ((function_index_ + FunctionEntry::kSize <= store_.length()) |
422 && (static_cast<int>(store_[function_index_]) == start)) { | 363 && (static_cast<int>(store_[function_index_]) == start)) { |
423 int index = function_index_; | 364 int index = function_index_; |
424 function_index_ += FunctionEntry::kSize; | 365 function_index_ += FunctionEntry::kSize; |
425 return FunctionEntry(store_.SubVector(index, | 366 return FunctionEntry(store_.SubVector(index, |
426 index + FunctionEntry::kSize)); | 367 index + FunctionEntry::kSize)); |
427 } | 368 } |
428 return FunctionEntry(); | 369 return FunctionEntry(); |
429 } | 370 } |
430 | 371 |
431 | 372 |
432 int ScriptDataImpl::GetSymbolIdentifier() { | 373 int ScriptDataImpl::GetSymbolIdentifier() { |
433 return ReadNumber(&symbol_data_); | 374 return ReadNumber(&symbol_data_); |
434 } | 375 } |
435 | 376 |
436 | 377 |
437 bool ScriptDataImpl::SanityCheck() { | 378 bool ScriptDataImpl::SanityCheck() { |
438 // Check that the header data is valid and doesn't specify | 379 // Check that the header data is valid and doesn't specify |
439 // point to positions outside the store. | 380 // point to positions outside the store. |
440 if (store_.length() < ScriptDataImpl::kHeaderSize) return false; | 381 if (store_.length() < PreparseDataConstants::kHeaderSize) return false; |
441 if (magic() != ScriptDataImpl::kMagicNumber) return false; | 382 if (magic() != PreparseDataConstants::kMagicNumber) return false; |
442 if (version() != ScriptDataImpl::kCurrentVersion) return false; | 383 if (version() != PreparseDataConstants::kCurrentVersion) return false; |
443 if (has_error()) { | 384 if (has_error()) { |
444 // Extra sane sanity check for error message encoding. | 385 // Extra sane sanity check for error message encoding. |
445 if (store_.length() <= kHeaderSize + kMessageTextPos) return false; | 386 if (store_.length() <= PreparseDataConstants::kHeaderSize |
446 if (Read(kMessageStartPos) > Read(kMessageEndPos)) return false; | 387 + PreparseDataConstants::kMessageTextPos) { |
447 unsigned arg_count = Read(kMessageArgCountPos); | 388 return false; |
448 int pos = kMessageTextPos; | 389 } |
| 390 if (Read(PreparseDataConstants::kMessageStartPos) > |
| 391 Read(PreparseDataConstants::kMessageEndPos)) { |
| 392 return false; |
| 393 } |
| 394 unsigned arg_count = Read(PreparseDataConstants::kMessageArgCountPos); |
| 395 int pos = PreparseDataConstants::kMessageTextPos; |
449 for (unsigned int i = 0; i <= arg_count; i++) { | 396 for (unsigned int i = 0; i <= arg_count; i++) { |
450 if (store_.length() <= kHeaderSize + pos) return false; | 397 if (store_.length() <= PreparseDataConstants::kHeaderSize + pos) { |
| 398 return false; |
| 399 } |
451 int length = static_cast<int>(Read(pos)); | 400 int length = static_cast<int>(Read(pos)); |
452 if (length < 0) return false; | 401 if (length < 0) return false; |
453 pos += 1 + length; | 402 pos += 1 + length; |
454 } | 403 } |
455 if (store_.length() < kHeaderSize + pos) return false; | 404 if (store_.length() < PreparseDataConstants::kHeaderSize + pos) { |
| 405 return false; |
| 406 } |
456 return true; | 407 return true; |
457 } | 408 } |
458 // Check that the space allocated for function entries is sane. | 409 // Check that the space allocated for function entries is sane. |
459 int functions_size = | 410 int functions_size = |
460 static_cast<int>(store_[ScriptDataImpl::kFunctionsSizeOffset]); | 411 static_cast<int>(store_[PreparseDataConstants::kFunctionsSizeOffset]); |
461 if (functions_size < 0) return false; | 412 if (functions_size < 0) return false; |
462 if (functions_size % FunctionEntry::kSize != 0) return false; | 413 if (functions_size % FunctionEntry::kSize != 0) return false; |
463 // Check that the count of symbols is non-negative. | 414 // Check that the count of symbols is non-negative. |
464 int symbol_count = | 415 int symbol_count = |
465 static_cast<int>(store_[ScriptDataImpl::kSymbolCountOffset]); | 416 static_cast<int>(store_[PreparseDataConstants::kSymbolCountOffset]); |
466 if (symbol_count < 0) return false; | 417 if (symbol_count < 0) return false; |
467 // Check that the total size has room for header and function entries. | 418 // Check that the total size has room for header and function entries. |
468 int minimum_size = | 419 int minimum_size = |
469 ScriptDataImpl::kHeaderSize + functions_size; | 420 PreparseDataConstants::kHeaderSize + functions_size; |
470 if (store_.length() < minimum_size) return false; | 421 if (store_.length() < minimum_size) return false; |
471 return true; | 422 return true; |
472 } | 423 } |
473 | 424 |
474 | 425 |
475 | 426 |
476 PartialParserRecorder::PartialParserRecorder() | |
477 : function_store_(0), | |
478 is_recording_(true), | |
479 pause_count_(0) { | |
480 preamble_[ScriptDataImpl::kMagicOffset] = ScriptDataImpl::kMagicNumber; | |
481 preamble_[ScriptDataImpl::kVersionOffset] = ScriptDataImpl::kCurrentVersion; | |
482 preamble_[ScriptDataImpl::kHasErrorOffset] = false; | |
483 preamble_[ScriptDataImpl::kFunctionsSizeOffset] = 0; | |
484 preamble_[ScriptDataImpl::kSymbolCountOffset] = 0; | |
485 preamble_[ScriptDataImpl::kSizeOffset] = 0; | |
486 ASSERT_EQ(6, ScriptDataImpl::kHeaderSize); | |
487 #ifdef DEBUG | |
488 prev_start_ = -1; | |
489 #endif | |
490 } | |
491 | |
492 | |
493 CompleteParserRecorder::CompleteParserRecorder() | |
494 : PartialParserRecorder(), | |
495 symbol_store_(0), | |
496 symbol_entries_(0), | |
497 symbol_table_(vector_compare), | |
498 symbol_id_(0) { | |
499 } | |
500 | |
501 | |
502 void PartialParserRecorder::WriteString(Vector<const char> str) { | |
503 function_store_.Add(str.length()); | |
504 for (int i = 0; i < str.length(); i++) { | |
505 function_store_.Add(str[i]); | |
506 } | |
507 } | |
508 | |
509 | |
510 void CompleteParserRecorder::WriteNumber(int number) { | |
511 ASSERT(number >= 0); | |
512 | |
513 int mask = (1 << 28) - 1; | |
514 for (int i = 28; i > 0; i -= 7) { | |
515 if (number > mask) { | |
516 symbol_store_.Add(static_cast<byte>(number >> i) | 0x80u); | |
517 number &= mask; | |
518 } | |
519 mask >>= 7; | |
520 } | |
521 symbol_store_.Add(static_cast<byte>(number)); | |
522 } | |
523 | |
524 | |
525 | |
526 const char* ScriptDataImpl::ReadString(unsigned* start, int* chars) { | 427 const char* ScriptDataImpl::ReadString(unsigned* start, int* chars) { |
527 int length = start[0]; | 428 int length = start[0]; |
528 char* result = NewArray<char>(length + 1); | 429 char* result = NewArray<char>(length + 1); |
529 for (int i = 0; i < length; i++) { | 430 for (int i = 0; i < length; i++) { |
530 result[i] = start[i + 1]; | 431 result[i] = start[i + 1]; |
531 } | 432 } |
532 result[length] = '\0'; | 433 result[length] = '\0'; |
533 if (chars != NULL) *chars = length; | 434 if (chars != NULL) *chars = length; |
534 return result; | 435 return result; |
535 } | 436 } |
536 | 437 |
537 | |
538 void PartialParserRecorder::LogMessage(Scanner::Location loc, | |
539 const char* message, | |
540 Vector<const char*> args) { | |
541 if (has_error()) return; | |
542 preamble_[ScriptDataImpl::kHasErrorOffset] = true; | |
543 function_store_.Reset(); | |
544 STATIC_ASSERT(ScriptDataImpl::kMessageStartPos == 0); | |
545 function_store_.Add(loc.beg_pos); | |
546 STATIC_ASSERT(ScriptDataImpl::kMessageEndPos == 1); | |
547 function_store_.Add(loc.end_pos); | |
548 STATIC_ASSERT(ScriptDataImpl::kMessageArgCountPos == 2); | |
549 function_store_.Add(args.length()); | |
550 STATIC_ASSERT(ScriptDataImpl::kMessageTextPos == 3); | |
551 WriteString(CStrVector(message)); | |
552 for (int i = 0; i < args.length(); i++) { | |
553 WriteString(CStrVector(args[i])); | |
554 } | |
555 is_recording_ = false; | |
556 } | |
557 | |
558 | |
559 Scanner::Location ScriptDataImpl::MessageLocation() { | 438 Scanner::Location ScriptDataImpl::MessageLocation() { |
560 int beg_pos = Read(kMessageStartPos); | 439 int beg_pos = Read(PreparseDataConstants::kMessageStartPos); |
561 int end_pos = Read(kMessageEndPos); | 440 int end_pos = Read(PreparseDataConstants::kMessageEndPos); |
562 return Scanner::Location(beg_pos, end_pos); | 441 return Scanner::Location(beg_pos, end_pos); |
563 } | 442 } |
564 | 443 |
565 | 444 |
566 const char* ScriptDataImpl::BuildMessage() { | 445 const char* ScriptDataImpl::BuildMessage() { |
567 unsigned* start = ReadAddress(kMessageTextPos); | 446 unsigned* start = ReadAddress(PreparseDataConstants::kMessageTextPos); |
568 return ReadString(start, NULL); | 447 return ReadString(start, NULL); |
569 } | 448 } |
570 | 449 |
571 | 450 |
572 Vector<const char*> ScriptDataImpl::BuildArgs() { | 451 Vector<const char*> ScriptDataImpl::BuildArgs() { |
573 int arg_count = Read(kMessageArgCountPos); | 452 int arg_count = Read(PreparseDataConstants::kMessageArgCountPos); |
574 const char** array = NewArray<const char*>(arg_count); | 453 const char** array = NewArray<const char*>(arg_count); |
575 // Position after text found by skipping past length field and | 454 // Position after text found by skipping past length field and |
576 // length field content words. | 455 // length field content words. |
577 int pos = kMessageTextPos + 1 + Read(kMessageTextPos); | 456 int pos = PreparseDataConstants::kMessageTextPos + 1 |
| 457 + Read(PreparseDataConstants::kMessageTextPos); |
578 for (int i = 0; i < arg_count; i++) { | 458 for (int i = 0; i < arg_count; i++) { |
579 int count = 0; | 459 int count = 0; |
580 array[i] = ReadString(ReadAddress(pos), &count); | 460 array[i] = ReadString(ReadAddress(pos), &count); |
581 pos += count + 1; | 461 pos += count + 1; |
582 } | 462 } |
583 return Vector<const char*>(array, arg_count); | 463 return Vector<const char*>(array, arg_count); |
584 } | 464 } |
585 | 465 |
586 | 466 |
587 unsigned ScriptDataImpl::Read(int position) { | 467 unsigned ScriptDataImpl::Read(int position) { |
588 return store_[ScriptDataImpl::kHeaderSize + position]; | 468 return store_[PreparseDataConstants::kHeaderSize + position]; |
589 } | 469 } |
590 | 470 |
591 | 471 |
592 unsigned* ScriptDataImpl::ReadAddress(int position) { | 472 unsigned* ScriptDataImpl::ReadAddress(int position) { |
593 return &store_[ScriptDataImpl::kHeaderSize + position]; | 473 return &store_[PreparseDataConstants::kHeaderSize + position]; |
594 } | 474 } |
595 | 475 |
596 | 476 |
597 Scope* Parser::NewScope(Scope* parent, Scope::Type type, bool inside_with) { | 477 Scope* Parser::NewScope(Scope* parent, Scope::Type type, bool inside_with) { |
598 Scope* result = new Scope(parent, type); | 478 Scope* result = new Scope(parent, type); |
599 result->Initialize(inside_with); | 479 result->Initialize(inside_with); |
600 return result; | 480 return result; |
601 } | 481 } |
602 | 482 |
603 // ---------------------------------------------------------------------------- | 483 // ---------------------------------------------------------------------------- |
(...skipping 3984 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4588 } | 4468 } |
4589 | 4469 |
4590 | 4470 |
4591 bool ScriptDataImpl::HasError() { | 4471 bool ScriptDataImpl::HasError() { |
4592 return has_error(); | 4472 return has_error(); |
4593 } | 4473 } |
4594 | 4474 |
4595 | 4475 |
4596 void ScriptDataImpl::Initialize() { | 4476 void ScriptDataImpl::Initialize() { |
4597 // Prepares state for use. | 4477 // Prepares state for use. |
4598 if (store_.length() >= kHeaderSize) { | 4478 if (store_.length() >= PreparseDataConstants::kHeaderSize) { |
4599 function_index_ = kHeaderSize; | 4479 function_index_ = PreparseDataConstants::kHeaderSize; |
4600 int symbol_data_offset = kHeaderSize + store_[kFunctionsSizeOffset]; | 4480 int symbol_data_offset = PreparseDataConstants::kHeaderSize |
| 4481 + store_[PreparseDataConstants::kFunctionsSizeOffset]; |
4601 if (store_.length() > symbol_data_offset) { | 4482 if (store_.length() > symbol_data_offset) { |
4602 symbol_data_ = reinterpret_cast<byte*>(&store_[symbol_data_offset]); | 4483 symbol_data_ = reinterpret_cast<byte*>(&store_[symbol_data_offset]); |
4603 } else { | 4484 } else { |
4604 // Partial preparse causes no symbol information. | 4485 // Partial preparse causes no symbol information. |
4605 symbol_data_ = reinterpret_cast<byte*>(&store_[0] + store_.length()); | 4486 symbol_data_ = reinterpret_cast<byte*>(&store_[0] + store_.length()); |
4606 } | 4487 } |
4607 symbol_data_end_ = reinterpret_cast<byte*>(&store_[0] + store_.length()); | 4488 symbol_data_end_ = reinterpret_cast<byte*>(&store_[0] + store_.length()); |
4608 } | 4489 } |
4609 } | 4490 } |
4610 | 4491 |
4611 | 4492 |
4612 int ScriptDataImpl::ReadNumber(byte** source) { | 4493 int ScriptDataImpl::ReadNumber(byte** source) { |
4613 // Reads a number from symbol_data_ in base 128. The most significant | 4494 // Reads a number from symbol_data_ in base 128. The most significant |
4614 // bit marks that there are more digits. | 4495 // bit marks that there are more digits. |
4615 // If the first byte is 0x80 (kNumberTerminator), it would normally | 4496 // If the first byte is 0x80 (kNumberTerminator), it would normally |
4616 // represent a leading zero. Since that is useless, and therefore won't | 4497 // represent a leading zero. Since that is useless, and therefore won't |
4617 // appear as the first digit of any actual value, it is used to | 4498 // appear as the first digit of any actual value, it is used to |
4618 // mark the end of the input stream. | 4499 // mark the end of the input stream. |
4619 byte* data = *source; | 4500 byte* data = *source; |
4620 if (data >= symbol_data_end_) return -1; | 4501 if (data >= symbol_data_end_) return -1; |
4621 byte input = *data; | 4502 byte input = *data; |
4622 if (input == kNumberTerminator) { | 4503 if (input == PreparseDataConstants::kNumberTerminator) { |
4623 // End of stream marker. | 4504 // End of stream marker. |
4624 return -1; | 4505 return -1; |
4625 } | 4506 } |
4626 int result = input & 0x7f; | 4507 int result = input & 0x7f; |
4627 data++; | 4508 data++; |
4628 while ((input & 0x80u) != 0) { | 4509 while ((input & 0x80u) != 0) { |
4629 if (data >= symbol_data_end_) return -1; | 4510 if (data >= symbol_data_end_) return -1; |
4630 input = *data; | 4511 input = *data; |
4631 result = (result << 7) | (input & 0x7f); | 4512 result = (result << 7) | (input & 0x7f); |
4632 data++; | 4513 data++; |
4633 } | 4514 } |
4634 *source = data; | 4515 *source = data; |
4635 return result; | 4516 return result; |
4636 } | 4517 } |
4637 | 4518 |
4638 | 4519 |
4639 // Create a Scanner for the preparser to use as input, and preparse the source. | 4520 // Create a Scanner for the preparser to use as input, and preparse the source. |
4640 static ScriptDataImpl* DoPreParse(Handle<String> source, | 4521 static ScriptDataImpl* DoPreParse(Handle<String> source, |
4641 unibrow::CharacterStream* stream, | 4522 unibrow::CharacterStream* stream, |
4642 bool allow_lazy, | 4523 bool allow_lazy, |
4643 PartialParserRecorder* recorder, | 4524 ParserRecorder* recorder, |
4644 int literal_flags) { | 4525 int literal_flags) { |
4645 V8JavaScriptScanner scanner; | 4526 V8JavaScriptScanner scanner; |
4646 scanner.Initialize(source, stream, literal_flags); | 4527 scanner.Initialize(source, stream, literal_flags); |
4647 preparser::PreParser<JavaScriptScanner, PartialParserRecorder> preparser; | 4528 preparser::PreParser preparser; |
4648 if (!preparser.PreParseProgram(&scanner, recorder, allow_lazy)) { | 4529 if (!preparser.PreParseProgram(&scanner, recorder, allow_lazy)) { |
4649 Top::StackOverflow(); | 4530 Top::StackOverflow(); |
4650 return NULL; | 4531 return NULL; |
4651 } | 4532 } |
4652 | 4533 |
4653 // Extract the accumulated data from the recorder as a single | 4534 // Extract the accumulated data from the recorder as a single |
4654 // contiguous vector that we are responsible for disposing. | 4535 // contiguous vector that we are responsible for disposing. |
4655 Vector<unsigned> store = recorder->ExtractData(); | 4536 Vector<unsigned> store = recorder->ExtractData(); |
4656 return new ScriptDataImpl(store); | 4537 return new ScriptDataImpl(store); |
4657 } | 4538 } |
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4737 Handle<String> source = Handle<String>(String::cast(script->source())); | 4618 Handle<String> source = Handle<String>(String::cast(script->source())); |
4738 result = parser.ParseProgram(source, info->is_global()); | 4619 result = parser.ParseProgram(source, info->is_global()); |
4739 } | 4620 } |
4740 } | 4621 } |
4741 | 4622 |
4742 info->SetFunction(result); | 4623 info->SetFunction(result); |
4743 return (result != NULL); | 4624 return (result != NULL); |
4744 } | 4625 } |
4745 | 4626 |
4746 } } // namespace v8::internal | 4627 } } // namespace v8::internal |
OLD | NEW |