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

Side by Side Diff: src/parser.cc

Issue 5545006: Optimized scanner to avoid virtual calls for every character read. (Closed)
Patch Set: Addressed review comments. Created 10 years 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
« no previous file with comments | « src/parser.h ('k') | src/preparser.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 591 matching lines...) Expand 10 before | Expand all | Expand 10 after
602 FunctionLiteral* Parser::ParseProgram(Handle<String> source, 602 FunctionLiteral* Parser::ParseProgram(Handle<String> source,
603 bool in_global_context) { 603 bool in_global_context) {
604 CompilationZoneScope zone_scope(DONT_DELETE_ON_EXIT); 604 CompilationZoneScope zone_scope(DONT_DELETE_ON_EXIT);
605 605
606 HistogramTimerScope timer(&Counters::parse); 606 HistogramTimerScope timer(&Counters::parse);
607 Counters::total_parse_size.Increment(source->length()); 607 Counters::total_parse_size.Increment(source->length());
608 fni_ = new FuncNameInferrer(); 608 fni_ = new FuncNameInferrer();
609 609
610 // Initialize parser state. 610 // Initialize parser state.
611 source->TryFlatten(); 611 source->TryFlatten();
612 scanner_.Initialize(source); 612 if (source->IsExternalTwoByteString()) {
613 // Notice that the stream is destroyed at the end of the branch block.
614 // The last line of the blocks can't be moved outside, even though they're
615 // identical calls.
616 ExternalTwoByteStringUC16CharacterStream stream(
617 Handle<ExternalTwoByteString>::cast(source), 0, source->length());
618 scanner_.Initialize(&stream, JavaScriptScanner::kAllLiterals);
619 return DoParseProgram(source, in_global_context, &zone_scope);
620 } else {
621 GenericStringUC16CharacterStream stream(source, 0, source->length());
622 scanner_.Initialize(&stream, JavaScriptScanner::kAllLiterals);
623 return DoParseProgram(source, in_global_context, &zone_scope);
624 }
625 }
626
627
628 FunctionLiteral* Parser::DoParseProgram(Handle<String> source,
629 bool in_global_context,
630 ZoneScope* zone_scope) {
613 ASSERT(target_stack_ == NULL); 631 ASSERT(target_stack_ == NULL);
614 if (pre_data_ != NULL) pre_data_->Initialize(); 632 if (pre_data_ != NULL) pre_data_->Initialize();
615 633
616 // Compute the parsing mode. 634 // Compute the parsing mode.
617 mode_ = FLAG_lazy ? PARSE_LAZILY : PARSE_EAGERLY; 635 mode_ = FLAG_lazy ? PARSE_LAZILY : PARSE_EAGERLY;
618 if (allow_natives_syntax_ || extension_ != NULL) mode_ = PARSE_EAGERLY; 636 if (allow_natives_syntax_ || extension_ != NULL) mode_ = PARSE_EAGERLY;
619 637
620 Scope::Type type = 638 Scope::Type type =
621 in_global_context 639 in_global_context
622 ? Scope::GLOBAL_SCOPE 640 ? Scope::GLOBAL_SCOPE
(...skipping 25 matching lines...) Expand all
648 } else if (stack_overflow_) { 666 } else if (stack_overflow_) {
649 Top::StackOverflow(); 667 Top::StackOverflow();
650 } 668 }
651 } 669 }
652 670
653 // Make sure the target stack is empty. 671 // Make sure the target stack is empty.
654 ASSERT(target_stack_ == NULL); 672 ASSERT(target_stack_ == NULL);
655 673
656 // If there was a syntax error we have to get rid of the AST 674 // If there was a syntax error we have to get rid of the AST
657 // and it is not safe to do so before the scope has been deleted. 675 // and it is not safe to do so before the scope has been deleted.
658 if (result == NULL) zone_scope.DeleteOnExit(); 676 if (result == NULL) zone_scope->DeleteOnExit();
659 return result; 677 return result;
660 } 678 }
661 679
662
663 FunctionLiteral* Parser::ParseLazy(Handle<SharedFunctionInfo> info) { 680 FunctionLiteral* Parser::ParseLazy(Handle<SharedFunctionInfo> info) {
664 CompilationZoneScope zone_scope(DONT_DELETE_ON_EXIT); 681 CompilationZoneScope zone_scope(DONT_DELETE_ON_EXIT);
665 HistogramTimerScope timer(&Counters::parse_lazy); 682 HistogramTimerScope timer(&Counters::parse_lazy);
666 Handle<String> source(String::cast(script_->source())); 683 Handle<String> source(String::cast(script_->source()));
667 Counters::total_parse_size.Increment(source->length()); 684 Counters::total_parse_size.Increment(source->length());
668 685
686 // Initialize parser state.
687 source->TryFlatten();
688 if (source->IsExternalTwoByteString()) {
689 ExternalTwoByteStringUC16CharacterStream stream(
690 Handle<ExternalTwoByteString>::cast(source),
691 info->start_position(),
692 info->end_position());
693 FunctionLiteral* result = ParseLazy(info, &stream, &zone_scope);
694 return result;
695 } else {
696 GenericStringUC16CharacterStream stream(source,
697 info->start_position(),
698 info->end_position());
699 FunctionLiteral* result = ParseLazy(info, &stream, &zone_scope);
700 return result;
701 }
702 }
703
704
705 FunctionLiteral* Parser::ParseLazy(Handle<SharedFunctionInfo> info,
706 UC16CharacterStream* source,
707 ZoneScope* zone_scope) {
708 scanner_.Initialize(source, JavaScriptScanner::kAllLiterals);
709 ASSERT(target_stack_ == NULL);
710
669 Handle<String> name(String::cast(info->name())); 711 Handle<String> name(String::cast(info->name()));
670 fni_ = new FuncNameInferrer(); 712 fni_ = new FuncNameInferrer();
671 fni_->PushEnclosingName(name); 713 fni_->PushEnclosingName(name);
672 714
673 // Initialize parser state.
674 source->TryFlatten();
675 scanner_.Initialize(source, info->start_position(), info->end_position());
676 ASSERT(target_stack_ == NULL);
677 mode_ = PARSE_EAGERLY; 715 mode_ = PARSE_EAGERLY;
678 716
679 // Place holder for the result. 717 // Place holder for the result.
680 FunctionLiteral* result = NULL; 718 FunctionLiteral* result = NULL;
681 719
682 { 720 {
683 // Parse the function literal. 721 // Parse the function literal.
684 Handle<String> no_name = Factory::empty_symbol(); 722 Handle<String> no_name = Factory::empty_symbol();
685 Scope* scope = 723 Scope* scope =
686 NewScope(top_scope_, Scope::GLOBAL_SCOPE, inside_with()); 724 NewScope(top_scope_, Scope::GLOBAL_SCOPE, inside_with());
(...skipping 11 matching lines...) Expand all
698 ASSERT(ok || stack_overflow_); 736 ASSERT(ok || stack_overflow_);
699 } 737 }
700 738
701 // Make sure the target stack is empty. 739 // Make sure the target stack is empty.
702 ASSERT(target_stack_ == NULL); 740 ASSERT(target_stack_ == NULL);
703 741
704 // If there was a stack overflow we have to get rid of AST and it is 742 // If there was a stack overflow we have to get rid of AST and it is
705 // not safe to do before scope has been deleted. 743 // not safe to do before scope has been deleted.
706 if (result == NULL) { 744 if (result == NULL) {
707 Top::StackOverflow(); 745 Top::StackOverflow();
708 zone_scope.DeleteOnExit(); 746 zone_scope->DeleteOnExit();
709 } else { 747 } else {
710 Handle<String> inferred_name(info->inferred_name()); 748 Handle<String> inferred_name(info->inferred_name());
711 result->set_inferred_name(inferred_name); 749 result->set_inferred_name(inferred_name);
712 } 750 }
713 return result; 751 return result;
714 } 752 }
715 753
716 754
717 Handle<String> Parser::GetSymbol(bool* ok) { 755 Handle<String> Parser::GetSymbol(bool* ok) {
718 int symbol_id = -1; 756 int symbol_id = -1;
719 if (pre_data() != NULL) { 757 if (pre_data() != NULL) {
720 symbol_id = pre_data()->GetSymbolIdentifier(); 758 symbol_id = pre_data()->GetSymbolIdentifier();
721 } 759 }
722 return LookupSymbol(symbol_id, scanner_.literal()); 760 return LookupSymbol(symbol_id, scanner().literal());
723 } 761 }
724 762
725 763
726 void Parser::ReportMessage(const char* type, Vector<const char*> args) { 764 void Parser::ReportMessage(const char* type, Vector<const char*> args) {
727 Scanner::Location source_location = scanner_.location(); 765 Scanner::Location source_location = scanner().location();
728 ReportMessageAt(source_location, type, args); 766 ReportMessageAt(source_location, type, args);
729 } 767 }
730 768
731 769
732 void Parser::ReportMessageAt(Scanner::Location source_location, 770 void Parser::ReportMessageAt(Scanner::Location source_location,
733 const char* type, 771 const char* type,
734 Vector<const char*> args) { 772 Vector<const char*> args) {
735 MessageLocation location(script_, 773 MessageLocation location(script_,
736 source_location.beg_pos, source_location.end_pos); 774 source_location.beg_pos, source_location.end_pos);
737 Handle<JSArray> array = Factory::NewJSArray(args.length()); 775 Handle<JSArray> array = Factory::NewJSArray(args.length());
(...skipping 896 matching lines...) Expand 10 before | Expand all | Expand 10 after
1634 } 1672 }
1635 1673
1636 1674
1637 Statement* Parser::ParseContinueStatement(bool* ok) { 1675 Statement* Parser::ParseContinueStatement(bool* ok) {
1638 // ContinueStatement :: 1676 // ContinueStatement ::
1639 // 'continue' Identifier? ';' 1677 // 'continue' Identifier? ';'
1640 1678
1641 Expect(Token::CONTINUE, CHECK_OK); 1679 Expect(Token::CONTINUE, CHECK_OK);
1642 Handle<String> label = Handle<String>::null(); 1680 Handle<String> label = Handle<String>::null();
1643 Token::Value tok = peek(); 1681 Token::Value tok = peek();
1644 if (!scanner_.has_line_terminator_before_next() && 1682 if (!scanner().has_line_terminator_before_next() &&
1645 tok != Token::SEMICOLON && tok != Token::RBRACE && tok != Token::EOS) { 1683 tok != Token::SEMICOLON && tok != Token::RBRACE && tok != Token::EOS) {
1646 label = ParseIdentifier(CHECK_OK); 1684 label = ParseIdentifier(CHECK_OK);
1647 } 1685 }
1648 IterationStatement* target = NULL; 1686 IterationStatement* target = NULL;
1649 target = LookupContinueTarget(label, CHECK_OK); 1687 target = LookupContinueTarget(label, CHECK_OK);
1650 if (target == NULL) { 1688 if (target == NULL) {
1651 // Illegal continue statement. To be consistent with KJS we delay 1689 // Illegal continue statement. To be consistent with KJS we delay
1652 // reporting of the syntax error until runtime. 1690 // reporting of the syntax error until runtime.
1653 Handle<String> error_type = Factory::illegal_continue_symbol(); 1691 Handle<String> error_type = Factory::illegal_continue_symbol();
1654 if (!label.is_null()) error_type = Factory::unknown_label_symbol(); 1692 if (!label.is_null()) error_type = Factory::unknown_label_symbol();
1655 Expression* throw_error = NewThrowSyntaxError(error_type, label); 1693 Expression* throw_error = NewThrowSyntaxError(error_type, label);
1656 return new ExpressionStatement(throw_error); 1694 return new ExpressionStatement(throw_error);
1657 } 1695 }
1658 ExpectSemicolon(CHECK_OK); 1696 ExpectSemicolon(CHECK_OK);
1659 return new ContinueStatement(target); 1697 return new ContinueStatement(target);
1660 } 1698 }
1661 1699
1662 1700
1663 Statement* Parser::ParseBreakStatement(ZoneStringList* labels, bool* ok) { 1701 Statement* Parser::ParseBreakStatement(ZoneStringList* labels, bool* ok) {
1664 // BreakStatement :: 1702 // BreakStatement ::
1665 // 'break' Identifier? ';' 1703 // 'break' Identifier? ';'
1666 1704
1667 Expect(Token::BREAK, CHECK_OK); 1705 Expect(Token::BREAK, CHECK_OK);
1668 Handle<String> label; 1706 Handle<String> label;
1669 Token::Value tok = peek(); 1707 Token::Value tok = peek();
1670 if (!scanner_.has_line_terminator_before_next() && 1708 if (!scanner().has_line_terminator_before_next() &&
1671 tok != Token::SEMICOLON && tok != Token::RBRACE && tok != Token::EOS) { 1709 tok != Token::SEMICOLON && tok != Token::RBRACE && tok != Token::EOS) {
1672 label = ParseIdentifier(CHECK_OK); 1710 label = ParseIdentifier(CHECK_OK);
1673 } 1711 }
1674 // Parse labeled break statements that target themselves into 1712 // Parse labeled break statements that target themselves into
1675 // empty statements, e.g. 'l1: l2: l3: break l2;' 1713 // empty statements, e.g. 'l1: l2: l3: break l2;'
1676 if (!label.is_null() && ContainsLabel(labels, label)) { 1714 if (!label.is_null() && ContainsLabel(labels, label)) {
1677 return EmptyStatement(); 1715 return EmptyStatement();
1678 } 1716 }
1679 BreakableStatement* target = NULL; 1717 BreakableStatement* target = NULL;
1680 target = LookupBreakTarget(label, CHECK_OK); 1718 target = LookupBreakTarget(label, CHECK_OK);
(...skipping 24 matching lines...) Expand all
1705 // function. See ECMA-262, section 12.9, page 67. 1743 // function. See ECMA-262, section 12.9, page 67.
1706 // 1744 //
1707 // To be consistent with KJS we report the syntax error at runtime. 1745 // To be consistent with KJS we report the syntax error at runtime.
1708 if (!top_scope_->is_function_scope()) { 1746 if (!top_scope_->is_function_scope()) {
1709 Handle<String> type = Factory::illegal_return_symbol(); 1747 Handle<String> type = Factory::illegal_return_symbol();
1710 Expression* throw_error = NewThrowSyntaxError(type, Handle<Object>::null()); 1748 Expression* throw_error = NewThrowSyntaxError(type, Handle<Object>::null());
1711 return new ExpressionStatement(throw_error); 1749 return new ExpressionStatement(throw_error);
1712 } 1750 }
1713 1751
1714 Token::Value tok = peek(); 1752 Token::Value tok = peek();
1715 if (scanner_.has_line_terminator_before_next() || 1753 if (scanner().has_line_terminator_before_next() ||
1716 tok == Token::SEMICOLON || 1754 tok == Token::SEMICOLON ||
1717 tok == Token::RBRACE || 1755 tok == Token::RBRACE ||
1718 tok == Token::EOS) { 1756 tok == Token::EOS) {
1719 ExpectSemicolon(CHECK_OK); 1757 ExpectSemicolon(CHECK_OK);
1720 return new ReturnStatement(GetLiteralUndefined()); 1758 return new ReturnStatement(GetLiteralUndefined());
1721 } 1759 }
1722 1760
1723 Expression* expr = ParseExpression(true, CHECK_OK); 1761 Expression* expr = ParseExpression(true, CHECK_OK);
1724 ExpectSemicolon(CHECK_OK); 1762 ExpectSemicolon(CHECK_OK);
1725 return new ReturnStatement(expr); 1763 return new ReturnStatement(expr);
(...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after
1837 return statement; 1875 return statement;
1838 } 1876 }
1839 1877
1840 1878
1841 Statement* Parser::ParseThrowStatement(bool* ok) { 1879 Statement* Parser::ParseThrowStatement(bool* ok) {
1842 // ThrowStatement :: 1880 // ThrowStatement ::
1843 // 'throw' Expression ';' 1881 // 'throw' Expression ';'
1844 1882
1845 Expect(Token::THROW, CHECK_OK); 1883 Expect(Token::THROW, CHECK_OK);
1846 int pos = scanner().location().beg_pos; 1884 int pos = scanner().location().beg_pos;
1847 if (scanner_.has_line_terminator_before_next()) { 1885 if (scanner().has_line_terminator_before_next()) {
1848 ReportMessage("newline_after_throw", Vector<const char*>::empty()); 1886 ReportMessage("newline_after_throw", Vector<const char*>::empty());
1849 *ok = false; 1887 *ok = false;
1850 return NULL; 1888 return NULL;
1851 } 1889 }
1852 Expression* exception = ParseExpression(true, CHECK_OK); 1890 Expression* exception = ParseExpression(true, CHECK_OK);
1853 ExpectSemicolon(CHECK_OK); 1891 ExpectSemicolon(CHECK_OK);
1854 1892
1855 return new ExpressionStatement(new Throw(exception, pos)); 1893 return new ExpressionStatement(new Throw(exception, pos));
1856 } 1894 }
1857 1895
(...skipping 543 matching lines...) Expand 10 before | Expand all | Expand 10 after
2401 return ParsePostfixExpression(ok); 2439 return ParsePostfixExpression(ok);
2402 } 2440 }
2403 } 2441 }
2404 2442
2405 2443
2406 Expression* Parser::ParsePostfixExpression(bool* ok) { 2444 Expression* Parser::ParsePostfixExpression(bool* ok) {
2407 // PostfixExpression :: 2445 // PostfixExpression ::
2408 // LeftHandSideExpression ('++' | '--')? 2446 // LeftHandSideExpression ('++' | '--')?
2409 2447
2410 Expression* expression = ParseLeftHandSideExpression(CHECK_OK); 2448 Expression* expression = ParseLeftHandSideExpression(CHECK_OK);
2411 if (!scanner_.has_line_terminator_before_next() && Token::IsCountOp(peek())) { 2449 if (!scanner().has_line_terminator_before_next() &&
2450 Token::IsCountOp(peek())) {
2412 // Signal a reference error if the expression is an invalid 2451 // Signal a reference error if the expression is an invalid
2413 // left-hand side expression. We could report this as a syntax 2452 // left-hand side expression. We could report this as a syntax
2414 // error here but for compatibility with JSC we choose to report the 2453 // error here but for compatibility with JSC we choose to report the
2415 // error at runtime. 2454 // error at runtime.
2416 if (expression == NULL || !expression->IsValidLeftHandSide()) { 2455 if (expression == NULL || !expression->IsValidLeftHandSide()) {
2417 Handle<String> type = Factory::invalid_lhs_in_postfix_op_symbol(); 2456 Handle<String> type = Factory::invalid_lhs_in_postfix_op_symbol();
2418 expression = NewThrowReferenceError(type); 2457 expression = NewThrowReferenceError(type);
2419 } 2458 }
2420 Token::Value next = Next(); 2459 Token::Value next = Next();
2421 int position = scanner().location().beg_pos; 2460 int position = scanner().location().beg_pos;
(...skipping 248 matching lines...) Expand 10 before | Expand all | Expand 10 after
2670 case Token::IDENTIFIER: { 2709 case Token::IDENTIFIER: {
2671 Handle<String> name = ParseIdentifier(CHECK_OK); 2710 Handle<String> name = ParseIdentifier(CHECK_OK);
2672 if (fni_ != NULL) fni_->PushVariableName(name); 2711 if (fni_ != NULL) fni_->PushVariableName(name);
2673 result = top_scope_->NewUnresolved(name, inside_with()); 2712 result = top_scope_->NewUnresolved(name, inside_with());
2674 break; 2713 break;
2675 } 2714 }
2676 2715
2677 case Token::NUMBER: { 2716 case Token::NUMBER: {
2678 Consume(Token::NUMBER); 2717 Consume(Token::NUMBER);
2679 double value = 2718 double value =
2680 StringToDouble(scanner_.literal(), ALLOW_HEX | ALLOW_OCTALS); 2719 StringToDouble(scanner().literal(), ALLOW_HEX | ALLOW_OCTALS);
2681 result = NewNumberLiteral(value); 2720 result = NewNumberLiteral(value);
2682 break; 2721 break;
2683 } 2722 }
2684 2723
2685 case Token::STRING: { 2724 case Token::STRING: {
2686 Consume(Token::STRING); 2725 Consume(Token::STRING);
2687 Handle<String> symbol = GetSymbol(CHECK_OK); 2726 Handle<String> symbol = GetSymbol(CHECK_OK);
2688 result = new Literal(symbol); 2727 result = new Literal(symbol);
2689 if (fni_ != NULL) fni_->PushLiteralName(symbol); 2728 if (fni_ != NULL) fni_->PushLiteralName(symbol);
2690 break; 2729 break;
(...skipping 330 matching lines...) Expand 10 before | Expand all | Expand 10 after
3021 if (!string.is_null() && string->AsArrayIndex(&index)) { 3060 if (!string.is_null() && string->AsArrayIndex(&index)) {
3022 key = NewNumberLiteral(index); 3061 key = NewNumberLiteral(index);
3023 break; 3062 break;
3024 } 3063 }
3025 key = new Literal(string); 3064 key = new Literal(string);
3026 break; 3065 break;
3027 } 3066 }
3028 case Token::NUMBER: { 3067 case Token::NUMBER: {
3029 Consume(Token::NUMBER); 3068 Consume(Token::NUMBER);
3030 double value = 3069 double value =
3031 StringToDouble(scanner_.literal(), ALLOW_HEX | ALLOW_OCTALS); 3070 StringToDouble(scanner().literal(), ALLOW_HEX | ALLOW_OCTALS);
3032 key = NewNumberLiteral(value); 3071 key = NewNumberLiteral(value);
3033 break; 3072 break;
3034 } 3073 }
3035 default: 3074 default:
3036 if (Token::IsKeyword(next)) { 3075 if (Token::IsKeyword(next)) {
3037 Consume(next); 3076 Consume(next);
3038 Handle<String> string = GetSymbol(CHECK_OK); 3077 Handle<String> string = GetSymbol(CHECK_OK);
3039 key = new Literal(string); 3078 key = new Literal(string);
3040 } else { 3079 } else {
3041 // Unexpected token. 3080 // Unexpected token.
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
3082 return new ObjectLiteral(constant_properties, 3121 return new ObjectLiteral(constant_properties,
3083 properties, 3122 properties,
3084 literal_index, 3123 literal_index,
3085 is_simple, 3124 is_simple,
3086 fast_elements, 3125 fast_elements,
3087 depth); 3126 depth);
3088 } 3127 }
3089 3128
3090 3129
3091 Expression* Parser::ParseRegExpLiteral(bool seen_equal, bool* ok) { 3130 Expression* Parser::ParseRegExpLiteral(bool seen_equal, bool* ok) {
3092 if (!scanner_.ScanRegExpPattern(seen_equal)) { 3131 if (!scanner().ScanRegExpPattern(seen_equal)) {
3093 Next(); 3132 Next();
3094 ReportMessage("unterminated_regexp", Vector<const char*>::empty()); 3133 ReportMessage("unterminated_regexp", Vector<const char*>::empty());
3095 *ok = false; 3134 *ok = false;
3096 return NULL; 3135 return NULL;
3097 } 3136 }
3098 3137
3099 int literal_index = temp_scope_->NextMaterializedLiteralIndex(); 3138 int literal_index = temp_scope_->NextMaterializedLiteralIndex();
3100 3139
3101 Handle<String> js_pattern = 3140 Handle<String> js_pattern =
3102 Factory::NewStringFromUtf8(scanner_.next_literal(), TENURED); 3141 Factory::NewStringFromUtf8(scanner().next_literal(), TENURED);
3103 scanner_.ScanRegExpFlags(); 3142 scanner().ScanRegExpFlags();
3104 Handle<String> js_flags = 3143 Handle<String> js_flags =
3105 Factory::NewStringFromUtf8(scanner_.next_literal(), TENURED); 3144 Factory::NewStringFromUtf8(scanner().next_literal(), TENURED);
3106 Next(); 3145 Next();
3107 3146
3108 return new RegExpLiteral(js_pattern, js_flags, literal_index); 3147 return new RegExpLiteral(js_pattern, js_flags, literal_index);
3109 } 3148 }
3110 3149
3111 3150
3112 ZoneList<Expression*>* Parser::ParseArguments(bool* ok) { 3151 ZoneList<Expression*>* Parser::ParseArguments(bool* ok) {
3113 // Arguments :: 3152 // Arguments ::
3114 // '(' (AssignmentExpression)*[','] ')' 3153 // '(' (AssignmentExpression)*[','] ')'
3115 3154
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
3151 { Scope* scope = 3190 { Scope* scope =
3152 NewScope(top_scope_, Scope::FUNCTION_SCOPE, inside_with()); 3191 NewScope(top_scope_, Scope::FUNCTION_SCOPE, inside_with());
3153 LexicalScope lexical_scope(&this->top_scope_, &this->with_nesting_level_, 3192 LexicalScope lexical_scope(&this->top_scope_, &this->with_nesting_level_,
3154 scope); 3193 scope);
3155 TemporaryScope temp_scope(&this->temp_scope_); 3194 TemporaryScope temp_scope(&this->temp_scope_);
3156 top_scope_->SetScopeName(name); 3195 top_scope_->SetScopeName(name);
3157 3196
3158 // FormalParameterList :: 3197 // FormalParameterList ::
3159 // '(' (Identifier)*[','] ')' 3198 // '(' (Identifier)*[','] ')'
3160 Expect(Token::LPAREN, CHECK_OK); 3199 Expect(Token::LPAREN, CHECK_OK);
3161 int start_pos = scanner_.location().beg_pos; 3200 int start_pos = scanner().location().beg_pos;
3162 bool done = (peek() == Token::RPAREN); 3201 bool done = (peek() == Token::RPAREN);
3163 while (!done) { 3202 while (!done) {
3164 Handle<String> param_name = ParseIdentifier(CHECK_OK); 3203 Handle<String> param_name = ParseIdentifier(CHECK_OK);
3165 top_scope_->AddParameter(top_scope_->DeclareLocal(param_name, 3204 top_scope_->AddParameter(top_scope_->DeclareLocal(param_name,
3166 Variable::VAR)); 3205 Variable::VAR));
3167 num_parameters++; 3206 num_parameters++;
3168 done = (peek() == Token::RPAREN); 3207 done = (peek() == Token::RPAREN);
3169 if (!done) Expect(Token::COMMA, CHECK_OK); 3208 if (!done) Expect(Token::COMMA, CHECK_OK);
3170 } 3209 }
3171 Expect(Token::RPAREN, CHECK_OK); 3210 Expect(Token::RPAREN, CHECK_OK);
(...skipping 16 matching lines...) Expand all
3188 new Assignment(Token::INIT_CONST, fproxy, 3227 new Assignment(Token::INIT_CONST, fproxy,
3189 new ThisFunction(), 3228 new ThisFunction(),
3190 RelocInfo::kNoPosition))); 3229 RelocInfo::kNoPosition)));
3191 } 3230 }
3192 3231
3193 // Determine if the function will be lazily compiled. The mode can 3232 // Determine if the function will be lazily compiled. The mode can
3194 // only be PARSE_LAZILY if the --lazy flag is true. 3233 // only be PARSE_LAZILY if the --lazy flag is true.
3195 bool is_lazily_compiled = 3234 bool is_lazily_compiled =
3196 mode() == PARSE_LAZILY && top_scope_->HasTrivialOuterContext(); 3235 mode() == PARSE_LAZILY && top_scope_->HasTrivialOuterContext();
3197 3236
3198 int function_block_pos = scanner_.location().beg_pos; 3237 int function_block_pos = scanner().location().beg_pos;
3199 int materialized_literal_count; 3238 int materialized_literal_count;
3200 int expected_property_count; 3239 int expected_property_count;
3201 int end_pos; 3240 int end_pos;
3202 bool only_simple_this_property_assignments; 3241 bool only_simple_this_property_assignments;
3203 Handle<FixedArray> this_property_assignments; 3242 Handle<FixedArray> this_property_assignments;
3204 if (is_lazily_compiled && pre_data() != NULL) { 3243 if (is_lazily_compiled && pre_data() != NULL) {
3205 FunctionEntry entry = pre_data()->GetFunctionEntry(function_block_pos); 3244 FunctionEntry entry = pre_data()->GetFunctionEntry(function_block_pos);
3206 if (!entry.is_valid()) { 3245 if (!entry.is_valid()) {
3207 ReportInvalidPreparseData(name, CHECK_OK); 3246 ReportInvalidPreparseData(name, CHECK_OK);
3208 } 3247 }
3209 end_pos = entry.end_pos(); 3248 end_pos = entry.end_pos();
3210 if (end_pos <= function_block_pos) { 3249 if (end_pos <= function_block_pos) {
3211 // End position greater than end of stream is safe, and hard to check. 3250 // End position greater than end of stream is safe, and hard to check.
3212 ReportInvalidPreparseData(name, CHECK_OK); 3251 ReportInvalidPreparseData(name, CHECK_OK);
3213 } 3252 }
3214 Counters::total_preparse_skipped.Increment(end_pos - function_block_pos); 3253 Counters::total_preparse_skipped.Increment(end_pos - function_block_pos);
3215 scanner_.SeekForward(end_pos); 3254 // Seek to position just before terminal '}'.
3255 scanner().SeekForward(end_pos - 1);
3216 materialized_literal_count = entry.literal_count(); 3256 materialized_literal_count = entry.literal_count();
3217 expected_property_count = entry.property_count(); 3257 expected_property_count = entry.property_count();
3218 only_simple_this_property_assignments = false; 3258 only_simple_this_property_assignments = false;
3219 this_property_assignments = Factory::empty_fixed_array(); 3259 this_property_assignments = Factory::empty_fixed_array();
3220 Expect(Token::RBRACE, CHECK_OK); 3260 Expect(Token::RBRACE, CHECK_OK);
3221 } else { 3261 } else {
3222 ParseSourceElements(body, Token::RBRACE, CHECK_OK); 3262 ParseSourceElements(body, Token::RBRACE, CHECK_OK);
3223 3263
3224 materialized_literal_count = temp_scope.materialized_literal_count(); 3264 materialized_literal_count = temp_scope.materialized_literal_count();
3225 expected_property_count = temp_scope.expected_property_count(); 3265 expected_property_count = temp_scope.expected_property_count();
3226 only_simple_this_property_assignments = 3266 only_simple_this_property_assignments =
3227 temp_scope.only_simple_this_property_assignments(); 3267 temp_scope.only_simple_this_property_assignments();
3228 this_property_assignments = temp_scope.this_property_assignments(); 3268 this_property_assignments = temp_scope.this_property_assignments();
3229 3269
3230 Expect(Token::RBRACE, CHECK_OK); 3270 Expect(Token::RBRACE, CHECK_OK);
3231 end_pos = scanner_.location().end_pos; 3271 end_pos = scanner().location().end_pos;
3232 } 3272 }
3233 3273
3234 FunctionLiteral* function_literal = 3274 FunctionLiteral* function_literal =
3235 new FunctionLiteral(name, 3275 new FunctionLiteral(name,
3236 top_scope_, 3276 top_scope_,
3237 body, 3277 body,
3238 materialized_literal_count, 3278 materialized_literal_count,
3239 expected_property_count, 3279 expected_property_count,
3240 only_simple_this_property_assignments, 3280 only_simple_this_property_assignments,
3241 this_property_assignments, 3281 this_property_assignments,
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after
3325 3365
3326 3366
3327 void Parser::ExpectSemicolon(bool* ok) { 3367 void Parser::ExpectSemicolon(bool* ok) {
3328 // Check for automatic semicolon insertion according to 3368 // Check for automatic semicolon insertion according to
3329 // the rules given in ECMA-262, section 7.9, page 21. 3369 // the rules given in ECMA-262, section 7.9, page 21.
3330 Token::Value tok = peek(); 3370 Token::Value tok = peek();
3331 if (tok == Token::SEMICOLON) { 3371 if (tok == Token::SEMICOLON) {
3332 Next(); 3372 Next();
3333 return; 3373 return;
3334 } 3374 }
3335 if (scanner_.has_line_terminator_before_next() || 3375 if (scanner().has_line_terminator_before_next() ||
3336 tok == Token::RBRACE || 3376 tok == Token::RBRACE ||
3337 tok == Token::EOS) { 3377 tok == Token::EOS) {
3338 return; 3378 return;
3339 } 3379 }
3340 Expect(Token::SEMICOLON, ok); 3380 Expect(Token::SEMICOLON, ok);
3341 } 3381 }
3342 3382
3343 3383
3344 Literal* Parser::GetLiteralUndefined() { 3384 Literal* Parser::GetLiteralUndefined() {
3345 return new Literal(Factory::undefined_value()); 3385 return new Literal(Factory::undefined_value());
(...skipping 30 matching lines...) Expand all
3376 3416
3377 // This function reads an identifier and determines whether or not it 3417 // This function reads an identifier and determines whether or not it
3378 // is 'get' or 'set'. The reason for not using ParseIdentifier and 3418 // is 'get' or 'set'. The reason for not using ParseIdentifier and
3379 // checking on the output is that this involves heap allocation which 3419 // checking on the output is that this involves heap allocation which
3380 // we can't do during preparsing. 3420 // we can't do during preparsing.
3381 Handle<String> Parser::ParseIdentifierOrGetOrSet(bool* is_get, 3421 Handle<String> Parser::ParseIdentifierOrGetOrSet(bool* is_get,
3382 bool* is_set, 3422 bool* is_set,
3383 bool* ok) { 3423 bool* ok) {
3384 Expect(Token::IDENTIFIER, ok); 3424 Expect(Token::IDENTIFIER, ok);
3385 if (!*ok) return Handle<String>(); 3425 if (!*ok) return Handle<String>();
3386 if (scanner_.literal_length() == 3) { 3426 if (scanner().literal_length() == 3) {
3387 const char* token = scanner_.literal_string(); 3427 const char* token = scanner().literal_string();
3388 *is_get = strcmp(token, "get") == 0; 3428 *is_get = strcmp(token, "get") == 0;
3389 *is_set = !*is_get && strcmp(token, "set") == 0; 3429 *is_set = !*is_get && strcmp(token, "set") == 0;
3390 } 3430 }
3391 return GetSymbol(ok); 3431 return GetSymbol(ok);
3392 } 3432 }
3393 3433
3394 3434
3395 // ---------------------------------------------------------------------------- 3435 // ----------------------------------------------------------------------------
3396 // Parser support 3436 // Parser support
3397 3437
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after
3496 ZoneList<Expression*>* args = new ZoneList<Expression*>(2); 3536 ZoneList<Expression*>* args = new ZoneList<Expression*>(2);
3497 args->Add(new Literal(type)); 3537 args->Add(new Literal(type));
3498 args->Add(new Literal(array)); 3538 args->Add(new Literal(array));
3499 return new Throw(new CallRuntime(constructor, NULL, args), 3539 return new Throw(new CallRuntime(constructor, NULL, args),
3500 scanner().location().beg_pos); 3540 scanner().location().beg_pos);
3501 } 3541 }
3502 3542
3503 // ---------------------------------------------------------------------------- 3543 // ----------------------------------------------------------------------------
3504 // JSON 3544 // JSON
3505 3545
3506 Handle<Object> JsonParser::ParseJson(Handle<String> source) { 3546 Handle<Object> JsonParser::ParseJson(Handle<String> script,
3507 source->TryFlatten(); 3547 UC16CharacterStream* source) {
3508 scanner_.Initialize(source); 3548 scanner_.Initialize(source);
3509 stack_overflow_ = false; 3549 stack_overflow_ = false;
3510 Handle<Object> result = ParseJsonValue(); 3550 Handle<Object> result = ParseJsonValue();
3511 if (result.is_null() || scanner_.Next() != Token::EOS) { 3551 if (result.is_null() || scanner_.Next() != Token::EOS) {
3512 if (stack_overflow_) { 3552 if (stack_overflow_) {
3513 // Scanner failed. 3553 // Scanner failed.
3514 Top::StackOverflow(); 3554 Top::StackOverflow();
3515 } else { 3555 } else {
3516 // Parse failed. Scanner's current token is the unexpected token. 3556 // Parse failed. Scanner's current token is the unexpected token.
3517 Token::Value token = scanner_.current_token(); 3557 Token::Value token = scanner_.current_token();
(...skipping 15 matching lines...) Expand all
3533 message = "unexpected_token_identifier"; 3573 message = "unexpected_token_identifier";
3534 break; 3574 break;
3535 default: 3575 default:
3536 message = "unexpected_token"; 3576 message = "unexpected_token";
3537 name_opt = Token::String(token); 3577 name_opt = Token::String(token);
3538 ASSERT(name_opt != NULL); 3578 ASSERT(name_opt != NULL);
3539 break; 3579 break;
3540 } 3580 }
3541 3581
3542 Scanner::Location source_location = scanner_.location(); 3582 Scanner::Location source_location = scanner_.location();
3543 MessageLocation location(Factory::NewScript(source), 3583 MessageLocation location(Factory::NewScript(script),
3544 source_location.beg_pos, 3584 source_location.beg_pos,
3545 source_location.end_pos); 3585 source_location.end_pos);
3546 int argc = (name_opt == NULL) ? 0 : 1; 3586 int argc = (name_opt == NULL) ? 0 : 1;
3547 Handle<JSArray> array = Factory::NewJSArray(argc); 3587 Handle<JSArray> array = Factory::NewJSArray(argc);
3548 if (name_opt != NULL) { 3588 if (name_opt != NULL) {
3549 SetElement(array, 3589 SetElement(array,
3550 0, 3590 0,
3551 Factory::NewStringFromUtf8(CStrVector(name_opt))); 3591 Factory::NewStringFromUtf8(CStrVector(name_opt)));
3552 } 3592 }
3553 Handle<Object> result = Factory::NewSyntaxError(message, array); 3593 Handle<Object> result = Factory::NewSyntaxError(message, array);
(...skipping 994 matching lines...) Expand 10 before | Expand all | Expand 10 after
4548 input = *data; 4588 input = *data;
4549 result = (result << 7) | (input & 0x7f); 4589 result = (result << 7) | (input & 0x7f);
4550 data++; 4590 data++;
4551 } 4591 }
4552 *source = data; 4592 *source = data;
4553 return result; 4593 return result;
4554 } 4594 }
4555 4595
4556 4596
4557 // Create a Scanner for the preparser to use as input, and preparse the source. 4597 // Create a Scanner for the preparser to use as input, and preparse the source.
4558 static ScriptDataImpl* DoPreParse(Handle<String> source, 4598 static ScriptDataImpl* DoPreParse(UC16CharacterStream* source,
4559 unibrow::CharacterStream* stream,
4560 bool allow_lazy, 4599 bool allow_lazy,
4561 ParserRecorder* recorder, 4600 ParserRecorder* recorder,
4562 int literal_flags) { 4601 int literal_flags) {
4563 V8JavaScriptScanner scanner; 4602 V8JavaScriptScanner scanner;
4564 scanner.Initialize(source, stream, literal_flags); 4603 scanner.Initialize(source, literal_flags);
4565 intptr_t stack_limit = StackGuard::real_climit(); 4604 intptr_t stack_limit = StackGuard::real_climit();
4566 if (!preparser::PreParser::PreParseProgram(&scanner, 4605 if (!preparser::PreParser::PreParseProgram(&scanner,
4567 recorder, 4606 recorder,
4568 allow_lazy, 4607 allow_lazy,
4569 stack_limit)) { 4608 stack_limit)) {
4570 Top::StackOverflow(); 4609 Top::StackOverflow();
4571 return NULL; 4610 return NULL;
4572 } 4611 }
4573 4612
4574 // Extract the accumulated data from the recorder as a single 4613 // Extract the accumulated data from the recorder as a single
4575 // contiguous vector that we are responsible for disposing. 4614 // contiguous vector that we are responsible for disposing.
4576 Vector<unsigned> store = recorder->ExtractData(); 4615 Vector<unsigned> store = recorder->ExtractData();
4577 return new ScriptDataImpl(store); 4616 return new ScriptDataImpl(store);
4578 } 4617 }
4579 4618
4580 4619
4581 // Preparse, but only collect data that is immediately useful, 4620 // Preparse, but only collect data that is immediately useful,
4582 // even if the preparser data is only used once. 4621 // even if the preparser data is only used once.
4583 ScriptDataImpl* ParserApi::PartialPreParse(Handle<String> source, 4622 ScriptDataImpl* ParserApi::PartialPreParse(UC16CharacterStream* source,
4584 unibrow::CharacterStream* stream,
4585 v8::Extension* extension) { 4623 v8::Extension* extension) {
4586 bool allow_lazy = FLAG_lazy && (extension == NULL); 4624 bool allow_lazy = FLAG_lazy && (extension == NULL);
4587 if (!allow_lazy) { 4625 if (!allow_lazy) {
4588 // Partial preparsing is only about lazily compiled functions. 4626 // Partial preparsing is only about lazily compiled functions.
4589 // If we don't allow lazy compilation, the log data will be empty. 4627 // If we don't allow lazy compilation, the log data will be empty.
4590 return NULL; 4628 return NULL;
4591 } 4629 }
4592 PartialParserRecorder recorder; 4630 PartialParserRecorder recorder;
4593 4631 return DoPreParse(source, allow_lazy, &recorder,
4594 return DoPreParse(source, stream, allow_lazy, &recorder,
4595 JavaScriptScanner::kNoLiterals); 4632 JavaScriptScanner::kNoLiterals);
4596 } 4633 }
4597 4634
4598 4635
4599 ScriptDataImpl* ParserApi::PreParse(Handle<String> source, 4636 ScriptDataImpl* ParserApi::PreParse(UC16CharacterStream* source,
4600 unibrow::CharacterStream* stream,
4601 v8::Extension* extension) { 4637 v8::Extension* extension) {
4602 Handle<Script> no_script; 4638 Handle<Script> no_script;
4603 bool allow_lazy = FLAG_lazy && (extension == NULL); 4639 bool allow_lazy = FLAG_lazy && (extension == NULL);
4604 CompleteParserRecorder recorder; 4640 CompleteParserRecorder recorder;
4605 int kPreParseLiteralsFlags = 4641 int kPreParseLiteralsFlags =
4606 JavaScriptScanner::kLiteralString | JavaScriptScanner::kLiteralIdentifier; 4642 JavaScriptScanner::kLiteralString | JavaScriptScanner::kLiteralIdentifier;
4607 return DoPreParse(source, stream, allow_lazy, 4643 return DoPreParse(source, allow_lazy, &recorder, kPreParseLiteralsFlags);
4608 &recorder, kPreParseLiteralsFlags);
4609 } 4644 }
4610 4645
4611 4646
4612 bool RegExpParser::ParseRegExp(FlatStringReader* input, 4647 bool RegExpParser::ParseRegExp(FlatStringReader* input,
4613 bool multiline, 4648 bool multiline,
4614 RegExpCompileData* result) { 4649 RegExpCompileData* result) {
4615 ASSERT(result != NULL); 4650 ASSERT(result != NULL);
4616 RegExpParser parser(input, &result->error, multiline); 4651 RegExpParser parser(input, &result->error, multiline);
4617 RegExpTree* tree = parser.ParsePattern(); 4652 RegExpTree* tree = parser.ParsePattern();
4618 if (parser.failed()) { 4653 if (parser.failed()) {
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
4658 Handle<String> source = Handle<String>(String::cast(script->source())); 4693 Handle<String> source = Handle<String>(String::cast(script->source()));
4659 result = parser.ParseProgram(source, info->is_global()); 4694 result = parser.ParseProgram(source, info->is_global());
4660 } 4695 }
4661 } 4696 }
4662 4697
4663 info->SetFunction(result); 4698 info->SetFunction(result);
4664 return (result != NULL); 4699 return (result != NULL);
4665 } 4700 }
4666 4701
4667 } } // namespace v8::internal 4702 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/parser.h ('k') | src/preparser.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698