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

Side by Side Diff: src/parser.cc

Issue 5545006: Optimized scanner to avoid virtual calls for every character read. (Closed)
Patch Set: 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
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 590 matching lines...) Expand 10 before | Expand all | Expand 10 after
601 FunctionLiteral* Parser::ParseProgram(Handle<String> source, 601 FunctionLiteral* Parser::ParseProgram(Handle<String> source,
602 bool in_global_context) { 602 bool in_global_context) {
603 CompilationZoneScope zone_scope(DONT_DELETE_ON_EXIT); 603 CompilationZoneScope zone_scope(DONT_DELETE_ON_EXIT);
604 604
605 HistogramTimerScope timer(&Counters::parse); 605 HistogramTimerScope timer(&Counters::parse);
606 Counters::total_parse_size.Increment(source->length()); 606 Counters::total_parse_size.Increment(source->length());
607 fni_ = new FuncNameInferrer(); 607 fni_ = new FuncNameInferrer();
608 608
609 // Initialize parser state. 609 // Initialize parser state.
610 source->TryFlatten(); 610 source->TryFlatten();
611 scanner_.Initialize(source); 611 if (source->IsExternalTwoByteString()) {
612 ExternalTwoByteStringUC16CharacterStream stream(
613 Handle<ExternalTwoByteString>::cast(source), 0, source->length());
614 scanner_.Initialize(&stream, JavaScriptScanner::kAllLiterals);
615 return DoParseProgram(source, in_global_context, &zone_scope);
Erik Corry 2010/12/07 12:27:30 This last line is common between both branches and
Lasse Reichstein 2010/12/07 14:05:54 The current code is mandated by the destructor of
616 } else {
617 GenericStringUC16CharacterStream stream(source, 0, source->length());
618 scanner_.Initialize(&stream, JavaScriptScanner::kAllLiterals);
619 return DoParseProgram(source, in_global_context, &zone_scope);
620 }
621 }
622
623
624 FunctionLiteral* Parser::DoParseProgram(Handle<String> source,
625 bool in_global_context,
626 ZoneScope* zone_scope) {
612 ASSERT(target_stack_ == NULL); 627 ASSERT(target_stack_ == NULL);
613 if (pre_data_ != NULL) pre_data_->Initialize(); 628 if (pre_data_ != NULL) pre_data_->Initialize();
614 629
615 // Compute the parsing mode. 630 // Compute the parsing mode.
616 mode_ = FLAG_lazy ? PARSE_LAZILY : PARSE_EAGERLY; 631 mode_ = FLAG_lazy ? PARSE_LAZILY : PARSE_EAGERLY;
617 if (allow_natives_syntax_ || extension_ != NULL) mode_ = PARSE_EAGERLY; 632 if (allow_natives_syntax_ || extension_ != NULL) mode_ = PARSE_EAGERLY;
618 633
619 Scope::Type type = 634 Scope::Type type =
620 in_global_context 635 in_global_context
621 ? Scope::GLOBAL_SCOPE 636 ? Scope::GLOBAL_SCOPE
(...skipping 25 matching lines...) Expand all
647 } else if (stack_overflow_) { 662 } else if (stack_overflow_) {
648 Top::StackOverflow(); 663 Top::StackOverflow();
649 } 664 }
650 } 665 }
651 666
652 // Make sure the target stack is empty. 667 // Make sure the target stack is empty.
653 ASSERT(target_stack_ == NULL); 668 ASSERT(target_stack_ == NULL);
654 669
655 // If there was a syntax error we have to get rid of the AST 670 // If there was a syntax error we have to get rid of the AST
656 // and it is not safe to do so before the scope has been deleted. 671 // and it is not safe to do so before the scope has been deleted.
657 if (result == NULL) zone_scope.DeleteOnExit(); 672 if (result == NULL) zone_scope->DeleteOnExit();
658 return result; 673 return result;
659 } 674 }
660 675
661
662 FunctionLiteral* Parser::ParseLazy(Handle<SharedFunctionInfo> info) { 676 FunctionLiteral* Parser::ParseLazy(Handle<SharedFunctionInfo> info) {
663 CompilationZoneScope zone_scope(DONT_DELETE_ON_EXIT); 677 CompilationZoneScope zone_scope(DONT_DELETE_ON_EXIT);
664 HistogramTimerScope timer(&Counters::parse_lazy); 678 HistogramTimerScope timer(&Counters::parse_lazy);
665 Handle<String> source(String::cast(script_->source())); 679 Handle<String> source(String::cast(script_->source()));
666 Counters::total_parse_size.Increment(source->length()); 680 Counters::total_parse_size.Increment(source->length());
667 681
682 // Initialize parser state.
683 source->TryFlatten();
684 if (source->IsExternalTwoByteString()) {
685 ExternalTwoByteStringUC16CharacterStream stream(
686 Handle<ExternalTwoByteString>::cast(source),
687 info->start_position(),
688 info->end_position());
689 FunctionLiteral* result = ParseLazy(info, &stream, &zone_scope);
690 return result;
691 } else {
692 GenericStringUC16CharacterStream stream(source,
693 info->start_position(),
694 info->end_position());
695 FunctionLiteral* result = ParseLazy(info, &stream, &zone_scope);
696 return result;
697 }
698 }
699
Erik Corry 2010/12/07 12:27:30 Missing blank line
700 FunctionLiteral* Parser::ParseLazy(Handle<SharedFunctionInfo> info,
701 UC16CharacterStream* source,
702 ZoneScope* zone_scope) {
703 scanner_.Initialize(source, JavaScriptScanner::kAllLiterals);
704 ASSERT(target_stack_ == NULL);
705
668 Handle<String> name(String::cast(info->name())); 706 Handle<String> name(String::cast(info->name()));
669 fni_ = new FuncNameInferrer(); 707 fni_ = new FuncNameInferrer();
670 fni_->PushEnclosingName(name); 708 fni_->PushEnclosingName(name);
671 709
672 // Initialize parser state.
673 source->TryFlatten();
674 scanner_.Initialize(source, info->start_position(), info->end_position());
675 ASSERT(target_stack_ == NULL);
676 mode_ = PARSE_EAGERLY; 710 mode_ = PARSE_EAGERLY;
677 711
678 // Place holder for the result. 712 // Place holder for the result.
679 FunctionLiteral* result = NULL; 713 FunctionLiteral* result = NULL;
680 714
681 { 715 {
682 // Parse the function literal. 716 // Parse the function literal.
683 Handle<String> no_name = Factory::empty_symbol(); 717 Handle<String> no_name = Factory::empty_symbol();
684 Scope* scope = 718 Scope* scope =
685 NewScope(top_scope_, Scope::GLOBAL_SCOPE, inside_with()); 719 NewScope(top_scope_, Scope::GLOBAL_SCOPE, inside_with());
(...skipping 11 matching lines...) Expand all
697 ASSERT(ok || stack_overflow_); 731 ASSERT(ok || stack_overflow_);
698 } 732 }
699 733
700 // Make sure the target stack is empty. 734 // Make sure the target stack is empty.
701 ASSERT(target_stack_ == NULL); 735 ASSERT(target_stack_ == NULL);
702 736
703 // If there was a stack overflow we have to get rid of AST and it is 737 // If there was a stack overflow we have to get rid of AST and it is
704 // not safe to do before scope has been deleted. 738 // not safe to do before scope has been deleted.
705 if (result == NULL) { 739 if (result == NULL) {
706 Top::StackOverflow(); 740 Top::StackOverflow();
707 zone_scope.DeleteOnExit(); 741 zone_scope->DeleteOnExit();
708 } 742 }
709 return result; 743 return result;
710 } 744 }
711 745
712 746
713 Handle<String> Parser::GetSymbol(bool* ok) { 747 Handle<String> Parser::GetSymbol(bool* ok) {
714 int symbol_id = -1; 748 int symbol_id = -1;
715 if (pre_data() != NULL) { 749 if (pre_data() != NULL) {
716 symbol_id = pre_data()->GetSymbolIdentifier(); 750 symbol_id = pre_data()->GetSymbolIdentifier();
717 } 751 }
718 return LookupSymbol(symbol_id, scanner_.literal()); 752 return LookupSymbol(symbol_id, scanner().literal());
719 } 753 }
720 754
721 755
722 void Parser::ReportMessage(const char* type, Vector<const char*> args) { 756 void Parser::ReportMessage(const char* type, Vector<const char*> args) {
723 Scanner::Location source_location = scanner_.location(); 757 Scanner::Location source_location = scanner().location();
724 ReportMessageAt(source_location, type, args); 758 ReportMessageAt(source_location, type, args);
725 } 759 }
726 760
727 761
728 void Parser::ReportMessageAt(Scanner::Location source_location, 762 void Parser::ReportMessageAt(Scanner::Location source_location,
729 const char* type, 763 const char* type,
730 Vector<const char*> args) { 764 Vector<const char*> args) {
731 MessageLocation location(script_, 765 MessageLocation location(script_,
732 source_location.beg_pos, source_location.end_pos); 766 source_location.beg_pos, source_location.end_pos);
733 Handle<JSArray> array = Factory::NewJSArray(args.length()); 767 Handle<JSArray> array = Factory::NewJSArray(args.length());
(...skipping 896 matching lines...) Expand 10 before | Expand all | Expand 10 after
1630 } 1664 }
1631 1665
1632 1666
1633 Statement* Parser::ParseContinueStatement(bool* ok) { 1667 Statement* Parser::ParseContinueStatement(bool* ok) {
1634 // ContinueStatement :: 1668 // ContinueStatement ::
1635 // 'continue' Identifier? ';' 1669 // 'continue' Identifier? ';'
1636 1670
1637 Expect(Token::CONTINUE, CHECK_OK); 1671 Expect(Token::CONTINUE, CHECK_OK);
1638 Handle<String> label = Handle<String>::null(); 1672 Handle<String> label = Handle<String>::null();
1639 Token::Value tok = peek(); 1673 Token::Value tok = peek();
1640 if (!scanner_.has_line_terminator_before_next() && 1674 if (!scanner().has_line_terminator_before_next() &&
1641 tok != Token::SEMICOLON && tok != Token::RBRACE && tok != Token::EOS) { 1675 tok != Token::SEMICOLON && tok != Token::RBRACE && tok != Token::EOS) {
1642 label = ParseIdentifier(CHECK_OK); 1676 label = ParseIdentifier(CHECK_OK);
1643 } 1677 }
1644 IterationStatement* target = NULL; 1678 IterationStatement* target = NULL;
1645 target = LookupContinueTarget(label, CHECK_OK); 1679 target = LookupContinueTarget(label, CHECK_OK);
1646 if (target == NULL) { 1680 if (target == NULL) {
1647 // Illegal continue statement. To be consistent with KJS we delay 1681 // Illegal continue statement. To be consistent with KJS we delay
1648 // reporting of the syntax error until runtime. 1682 // reporting of the syntax error until runtime.
1649 Handle<String> error_type = Factory::illegal_continue_symbol(); 1683 Handle<String> error_type = Factory::illegal_continue_symbol();
1650 if (!label.is_null()) error_type = Factory::unknown_label_symbol(); 1684 if (!label.is_null()) error_type = Factory::unknown_label_symbol();
1651 Expression* throw_error = NewThrowSyntaxError(error_type, label); 1685 Expression* throw_error = NewThrowSyntaxError(error_type, label);
1652 return new ExpressionStatement(throw_error); 1686 return new ExpressionStatement(throw_error);
1653 } 1687 }
1654 ExpectSemicolon(CHECK_OK); 1688 ExpectSemicolon(CHECK_OK);
1655 return new ContinueStatement(target); 1689 return new ContinueStatement(target);
1656 } 1690 }
1657 1691
1658 1692
1659 Statement* Parser::ParseBreakStatement(ZoneStringList* labels, bool* ok) { 1693 Statement* Parser::ParseBreakStatement(ZoneStringList* labels, bool* ok) {
1660 // BreakStatement :: 1694 // BreakStatement ::
1661 // 'break' Identifier? ';' 1695 // 'break' Identifier? ';'
1662 1696
1663 Expect(Token::BREAK, CHECK_OK); 1697 Expect(Token::BREAK, CHECK_OK);
1664 Handle<String> label; 1698 Handle<String> label;
1665 Token::Value tok = peek(); 1699 Token::Value tok = peek();
1666 if (!scanner_.has_line_terminator_before_next() && 1700 if (!scanner().has_line_terminator_before_next() &&
1667 tok != Token::SEMICOLON && tok != Token::RBRACE && tok != Token::EOS) { 1701 tok != Token::SEMICOLON && tok != Token::RBRACE && tok != Token::EOS) {
1668 label = ParseIdentifier(CHECK_OK); 1702 label = ParseIdentifier(CHECK_OK);
1669 } 1703 }
1670 // Parse labeled break statements that target themselves into 1704 // Parse labeled break statements that target themselves into
1671 // empty statements, e.g. 'l1: l2: l3: break l2;' 1705 // empty statements, e.g. 'l1: l2: l3: break l2;'
1672 if (!label.is_null() && ContainsLabel(labels, label)) { 1706 if (!label.is_null() && ContainsLabel(labels, label)) {
1673 return EmptyStatement(); 1707 return EmptyStatement();
1674 } 1708 }
1675 BreakableStatement* target = NULL; 1709 BreakableStatement* target = NULL;
1676 target = LookupBreakTarget(label, CHECK_OK); 1710 target = LookupBreakTarget(label, CHECK_OK);
(...skipping 24 matching lines...) Expand all
1701 // function. See ECMA-262, section 12.9, page 67. 1735 // function. See ECMA-262, section 12.9, page 67.
1702 // 1736 //
1703 // To be consistent with KJS we report the syntax error at runtime. 1737 // To be consistent with KJS we report the syntax error at runtime.
1704 if (!top_scope_->is_function_scope()) { 1738 if (!top_scope_->is_function_scope()) {
1705 Handle<String> type = Factory::illegal_return_symbol(); 1739 Handle<String> type = Factory::illegal_return_symbol();
1706 Expression* throw_error = NewThrowSyntaxError(type, Handle<Object>::null()); 1740 Expression* throw_error = NewThrowSyntaxError(type, Handle<Object>::null());
1707 return new ExpressionStatement(throw_error); 1741 return new ExpressionStatement(throw_error);
1708 } 1742 }
1709 1743
1710 Token::Value tok = peek(); 1744 Token::Value tok = peek();
1711 if (scanner_.has_line_terminator_before_next() || 1745 if (scanner().has_line_terminator_before_next() ||
1712 tok == Token::SEMICOLON || 1746 tok == Token::SEMICOLON ||
1713 tok == Token::RBRACE || 1747 tok == Token::RBRACE ||
1714 tok == Token::EOS) { 1748 tok == Token::EOS) {
1715 ExpectSemicolon(CHECK_OK); 1749 ExpectSemicolon(CHECK_OK);
1716 return new ReturnStatement(GetLiteralUndefined()); 1750 return new ReturnStatement(GetLiteralUndefined());
1717 } 1751 }
1718 1752
1719 Expression* expr = ParseExpression(true, CHECK_OK); 1753 Expression* expr = ParseExpression(true, CHECK_OK);
1720 ExpectSemicolon(CHECK_OK); 1754 ExpectSemicolon(CHECK_OK);
1721 return new ReturnStatement(expr); 1755 return new ReturnStatement(expr);
(...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after
1833 return statement; 1867 return statement;
1834 } 1868 }
1835 1869
1836 1870
1837 Statement* Parser::ParseThrowStatement(bool* ok) { 1871 Statement* Parser::ParseThrowStatement(bool* ok) {
1838 // ThrowStatement :: 1872 // ThrowStatement ::
1839 // 'throw' Expression ';' 1873 // 'throw' Expression ';'
1840 1874
1841 Expect(Token::THROW, CHECK_OK); 1875 Expect(Token::THROW, CHECK_OK);
1842 int pos = scanner().location().beg_pos; 1876 int pos = scanner().location().beg_pos;
1843 if (scanner_.has_line_terminator_before_next()) { 1877 if (scanner().has_line_terminator_before_next()) {
1844 ReportMessage("newline_after_throw", Vector<const char*>::empty()); 1878 ReportMessage("newline_after_throw", Vector<const char*>::empty());
1845 *ok = false; 1879 *ok = false;
1846 return NULL; 1880 return NULL;
1847 } 1881 }
1848 Expression* exception = ParseExpression(true, CHECK_OK); 1882 Expression* exception = ParseExpression(true, CHECK_OK);
1849 ExpectSemicolon(CHECK_OK); 1883 ExpectSemicolon(CHECK_OK);
1850 1884
1851 return new ExpressionStatement(new Throw(exception, pos)); 1885 return new ExpressionStatement(new Throw(exception, pos));
1852 } 1886 }
1853 1887
(...skipping 540 matching lines...) Expand 10 before | Expand all | Expand 10 after
2394 return ParsePostfixExpression(ok); 2428 return ParsePostfixExpression(ok);
2395 } 2429 }
2396 } 2430 }
2397 2431
2398 2432
2399 Expression* Parser::ParsePostfixExpression(bool* ok) { 2433 Expression* Parser::ParsePostfixExpression(bool* ok) {
2400 // PostfixExpression :: 2434 // PostfixExpression ::
2401 // LeftHandSideExpression ('++' | '--')? 2435 // LeftHandSideExpression ('++' | '--')?
2402 2436
2403 Expression* expression = ParseLeftHandSideExpression(CHECK_OK); 2437 Expression* expression = ParseLeftHandSideExpression(CHECK_OK);
2404 if (!scanner_.has_line_terminator_before_next() && Token::IsCountOp(peek())) { 2438 if (!scanner().has_line_terminator_before_next()
2439 && Token::IsCountOp(peek())) {
Erik Corry 2010/12/07 12:27:30 Everywhere else in this file seems to have the &&
Lasse Reichstein 2010/12/07 14:05:54 I prefer having them on the second line, but let's
Vitaly Repeshko 2010/12/07 14:15:50 Please don't :) While http://google-styleguide.go
2405 // Signal a reference error if the expression is an invalid 2440 // Signal a reference error if the expression is an invalid
2406 // left-hand side expression. We could report this as a syntax 2441 // left-hand side expression. We could report this as a syntax
2407 // error here but for compatibility with JSC we choose to report the 2442 // error here but for compatibility with JSC we choose to report the
2408 // error at runtime. 2443 // error at runtime.
2409 if (expression == NULL || !expression->IsValidLeftHandSide()) { 2444 if (expression == NULL || !expression->IsValidLeftHandSide()) {
2410 Handle<String> type = Factory::invalid_lhs_in_postfix_op_symbol(); 2445 Handle<String> type = Factory::invalid_lhs_in_postfix_op_symbol();
2411 expression = NewThrowReferenceError(type); 2446 expression = NewThrowReferenceError(type);
2412 } 2447 }
2413 Token::Value next = Next(); 2448 Token::Value next = Next();
2414 int position = scanner().location().beg_pos; 2449 int position = scanner().location().beg_pos;
(...skipping 248 matching lines...) Expand 10 before | Expand all | Expand 10 after
2663 case Token::IDENTIFIER: { 2698 case Token::IDENTIFIER: {
2664 Handle<String> name = ParseIdentifier(CHECK_OK); 2699 Handle<String> name = ParseIdentifier(CHECK_OK);
2665 if (fni_ != NULL) fni_->PushVariableName(name); 2700 if (fni_ != NULL) fni_->PushVariableName(name);
2666 result = top_scope_->NewUnresolved(name, inside_with()); 2701 result = top_scope_->NewUnresolved(name, inside_with());
2667 break; 2702 break;
2668 } 2703 }
2669 2704
2670 case Token::NUMBER: { 2705 case Token::NUMBER: {
2671 Consume(Token::NUMBER); 2706 Consume(Token::NUMBER);
2672 double value = 2707 double value =
2673 StringToDouble(scanner_.literal(), ALLOW_HEX | ALLOW_OCTALS); 2708 StringToDouble(scanner().literal(), ALLOW_HEX | ALLOW_OCTALS);
2674 result = NewNumberLiteral(value); 2709 result = NewNumberLiteral(value);
2675 break; 2710 break;
2676 } 2711 }
2677 2712
2678 case Token::STRING: { 2713 case Token::STRING: {
2679 Consume(Token::STRING); 2714 Consume(Token::STRING);
2680 Handle<String> symbol = GetSymbol(CHECK_OK); 2715 Handle<String> symbol = GetSymbol(CHECK_OK);
2681 result = new Literal(symbol); 2716 result = new Literal(symbol);
2682 if (fni_ != NULL) fni_->PushLiteralName(symbol); 2717 if (fni_ != NULL) fni_->PushLiteralName(symbol);
2683 break; 2718 break;
(...skipping 329 matching lines...) Expand 10 before | Expand all | Expand 10 after
3013 if (!string.is_null() && string->AsArrayIndex(&index)) { 3048 if (!string.is_null() && string->AsArrayIndex(&index)) {
3014 key = NewNumberLiteral(index); 3049 key = NewNumberLiteral(index);
3015 break; 3050 break;
3016 } 3051 }
3017 key = new Literal(string); 3052 key = new Literal(string);
3018 break; 3053 break;
3019 } 3054 }
3020 case Token::NUMBER: { 3055 case Token::NUMBER: {
3021 Consume(Token::NUMBER); 3056 Consume(Token::NUMBER);
3022 double value = 3057 double value =
3023 StringToDouble(scanner_.literal(), ALLOW_HEX | ALLOW_OCTALS); 3058 StringToDouble(scanner().literal(), ALLOW_HEX | ALLOW_OCTALS);
3024 key = NewNumberLiteral(value); 3059 key = NewNumberLiteral(value);
3025 break; 3060 break;
3026 } 3061 }
3027 default: 3062 default:
3028 if (Token::IsKeyword(next)) { 3063 if (Token::IsKeyword(next)) {
3029 Consume(next); 3064 Consume(next);
3030 Handle<String> string = GetSymbol(CHECK_OK); 3065 Handle<String> string = GetSymbol(CHECK_OK);
3031 key = new Literal(string); 3066 key = new Literal(string);
3032 } else { 3067 } else {
3033 // Unexpected token. 3068 // Unexpected token.
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
3074 return new ObjectLiteral(constant_properties, 3109 return new ObjectLiteral(constant_properties,
3075 properties, 3110 properties,
3076 literal_index, 3111 literal_index,
3077 is_simple, 3112 is_simple,
3078 fast_elements, 3113 fast_elements,
3079 depth); 3114 depth);
3080 } 3115 }
3081 3116
3082 3117
3083 Expression* Parser::ParseRegExpLiteral(bool seen_equal, bool* ok) { 3118 Expression* Parser::ParseRegExpLiteral(bool seen_equal, bool* ok) {
3084 if (!scanner_.ScanRegExpPattern(seen_equal)) { 3119 if (!scanner().ScanRegExpPattern(seen_equal)) {
3085 Next(); 3120 Next();
3086 ReportMessage("unterminated_regexp", Vector<const char*>::empty()); 3121 ReportMessage("unterminated_regexp", Vector<const char*>::empty());
3087 *ok = false; 3122 *ok = false;
3088 return NULL; 3123 return NULL;
3089 } 3124 }
3090 3125
3091 int literal_index = temp_scope_->NextMaterializedLiteralIndex(); 3126 int literal_index = temp_scope_->NextMaterializedLiteralIndex();
3092 3127
3093 Handle<String> js_pattern = 3128 Handle<String> js_pattern =
3094 Factory::NewStringFromUtf8(scanner_.next_literal(), TENURED); 3129 Factory::NewStringFromUtf8(scanner().next_literal(), TENURED);
3095 scanner_.ScanRegExpFlags(); 3130 scanner().ScanRegExpFlags();
3096 Handle<String> js_flags = 3131 Handle<String> js_flags =
3097 Factory::NewStringFromUtf8(scanner_.next_literal(), TENURED); 3132 Factory::NewStringFromUtf8(scanner().next_literal(), TENURED);
3098 Next(); 3133 Next();
3099 3134
3100 return new RegExpLiteral(js_pattern, js_flags, literal_index); 3135 return new RegExpLiteral(js_pattern, js_flags, literal_index);
3101 } 3136 }
3102 3137
3103 3138
3104 ZoneList<Expression*>* Parser::ParseArguments(bool* ok) { 3139 ZoneList<Expression*>* Parser::ParseArguments(bool* ok) {
3105 // Arguments :: 3140 // Arguments ::
3106 // '(' (AssignmentExpression)*[','] ')' 3141 // '(' (AssignmentExpression)*[','] ')'
3107 3142
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
3143 { Scope* scope = 3178 { Scope* scope =
3144 NewScope(top_scope_, Scope::FUNCTION_SCOPE, inside_with()); 3179 NewScope(top_scope_, Scope::FUNCTION_SCOPE, inside_with());
3145 LexicalScope lexical_scope(&this->top_scope_, &this->with_nesting_level_, 3180 LexicalScope lexical_scope(&this->top_scope_, &this->with_nesting_level_,
3146 scope); 3181 scope);
3147 TemporaryScope temp_scope(&this->temp_scope_); 3182 TemporaryScope temp_scope(&this->temp_scope_);
3148 top_scope_->SetScopeName(name); 3183 top_scope_->SetScopeName(name);
3149 3184
3150 // FormalParameterList :: 3185 // FormalParameterList ::
3151 // '(' (Identifier)*[','] ')' 3186 // '(' (Identifier)*[','] ')'
3152 Expect(Token::LPAREN, CHECK_OK); 3187 Expect(Token::LPAREN, CHECK_OK);
3153 int start_pos = scanner_.location().beg_pos; 3188 int start_pos = scanner().location().beg_pos;
3154 bool done = (peek() == Token::RPAREN); 3189 bool done = (peek() == Token::RPAREN);
3155 while (!done) { 3190 while (!done) {
3156 Handle<String> param_name = ParseIdentifier(CHECK_OK); 3191 Handle<String> param_name = ParseIdentifier(CHECK_OK);
3157 top_scope_->AddParameter(top_scope_->DeclareLocal(param_name, 3192 top_scope_->AddParameter(top_scope_->DeclareLocal(param_name,
3158 Variable::VAR)); 3193 Variable::VAR));
3159 num_parameters++; 3194 num_parameters++;
3160 done = (peek() == Token::RPAREN); 3195 done = (peek() == Token::RPAREN);
3161 if (!done) Expect(Token::COMMA, CHECK_OK); 3196 if (!done) Expect(Token::COMMA, CHECK_OK);
3162 } 3197 }
3163 Expect(Token::RPAREN, CHECK_OK); 3198 Expect(Token::RPAREN, CHECK_OK);
(...skipping 16 matching lines...) Expand all
3180 new Assignment(Token::INIT_CONST, fproxy, 3215 new Assignment(Token::INIT_CONST, fproxy,
3181 new ThisFunction(), 3216 new ThisFunction(),
3182 RelocInfo::kNoPosition))); 3217 RelocInfo::kNoPosition)));
3183 } 3218 }
3184 3219
3185 // Determine if the function will be lazily compiled. The mode can 3220 // Determine if the function will be lazily compiled. The mode can
3186 // only be PARSE_LAZILY if the --lazy flag is true. 3221 // only be PARSE_LAZILY if the --lazy flag is true.
3187 bool is_lazily_compiled = 3222 bool is_lazily_compiled =
3188 mode() == PARSE_LAZILY && top_scope_->HasTrivialOuterContext(); 3223 mode() == PARSE_LAZILY && top_scope_->HasTrivialOuterContext();
3189 3224
3190 int function_block_pos = scanner_.location().beg_pos; 3225 int function_block_pos = scanner().location().beg_pos;
3191 int materialized_literal_count; 3226 int materialized_literal_count;
3192 int expected_property_count; 3227 int expected_property_count;
3193 int end_pos; 3228 int end_pos;
3194 bool only_simple_this_property_assignments; 3229 bool only_simple_this_property_assignments;
3195 Handle<FixedArray> this_property_assignments; 3230 Handle<FixedArray> this_property_assignments;
3196 if (is_lazily_compiled && pre_data() != NULL) { 3231 if (is_lazily_compiled && pre_data() != NULL) {
3197 FunctionEntry entry = pre_data()->GetFunctionEntry(function_block_pos); 3232 FunctionEntry entry = pre_data()->GetFunctionEntry(function_block_pos);
3198 if (!entry.is_valid()) { 3233 if (!entry.is_valid()) {
3199 ReportInvalidPreparseData(name, CHECK_OK); 3234 ReportInvalidPreparseData(name, CHECK_OK);
3200 } 3235 }
3201 end_pos = entry.end_pos(); 3236 end_pos = entry.end_pos();
3202 if (end_pos <= function_block_pos) { 3237 if (end_pos <= function_block_pos) {
3203 // End position greater than end of stream is safe, and hard to check. 3238 // End position greater than end of stream is safe, and hard to check.
3204 ReportInvalidPreparseData(name, CHECK_OK); 3239 ReportInvalidPreparseData(name, CHECK_OK);
3205 } 3240 }
3206 Counters::total_preparse_skipped.Increment(end_pos - function_block_pos); 3241 Counters::total_preparse_skipped.Increment(end_pos - function_block_pos);
3207 scanner_.SeekForward(end_pos); 3242 // Seek to position just before terminal '}'.
3243 scanner().SeekForward(end_pos - 1);
3208 materialized_literal_count = entry.literal_count(); 3244 materialized_literal_count = entry.literal_count();
3209 expected_property_count = entry.property_count(); 3245 expected_property_count = entry.property_count();
3210 only_simple_this_property_assignments = false; 3246 only_simple_this_property_assignments = false;
3211 this_property_assignments = Factory::empty_fixed_array(); 3247 this_property_assignments = Factory::empty_fixed_array();
3212 Expect(Token::RBRACE, CHECK_OK); 3248 Expect(Token::RBRACE, CHECK_OK);
3213 } else { 3249 } else {
3214 ParseSourceElements(body, Token::RBRACE, CHECK_OK); 3250 ParseSourceElements(body, Token::RBRACE, CHECK_OK);
3215 3251
3216 materialized_literal_count = temp_scope.materialized_literal_count(); 3252 materialized_literal_count = temp_scope.materialized_literal_count();
3217 expected_property_count = temp_scope.expected_property_count(); 3253 expected_property_count = temp_scope.expected_property_count();
3218 only_simple_this_property_assignments = 3254 only_simple_this_property_assignments =
3219 temp_scope.only_simple_this_property_assignments(); 3255 temp_scope.only_simple_this_property_assignments();
3220 this_property_assignments = temp_scope.this_property_assignments(); 3256 this_property_assignments = temp_scope.this_property_assignments();
3221 3257
3222 Expect(Token::RBRACE, CHECK_OK); 3258 Expect(Token::RBRACE, CHECK_OK);
3223 end_pos = scanner_.location().end_pos; 3259 end_pos = scanner().location().end_pos;
3224 } 3260 }
3225 3261
3226 FunctionLiteral* function_literal = 3262 FunctionLiteral* function_literal =
3227 new FunctionLiteral(name, 3263 new FunctionLiteral(name,
3228 top_scope_, 3264 top_scope_,
3229 body, 3265 body,
3230 materialized_literal_count, 3266 materialized_literal_count,
3231 expected_property_count, 3267 expected_property_count,
3232 only_simple_this_property_assignments, 3268 only_simple_this_property_assignments,
3233 this_property_assignments, 3269 this_property_assignments,
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after
3317 3353
3318 3354
3319 void Parser::ExpectSemicolon(bool* ok) { 3355 void Parser::ExpectSemicolon(bool* ok) {
3320 // Check for automatic semicolon insertion according to 3356 // Check for automatic semicolon insertion according to
3321 // the rules given in ECMA-262, section 7.9, page 21. 3357 // the rules given in ECMA-262, section 7.9, page 21.
3322 Token::Value tok = peek(); 3358 Token::Value tok = peek();
3323 if (tok == Token::SEMICOLON) { 3359 if (tok == Token::SEMICOLON) {
3324 Next(); 3360 Next();
3325 return; 3361 return;
3326 } 3362 }
3327 if (scanner_.has_line_terminator_before_next() || 3363 if (scanner().has_line_terminator_before_next() ||
3328 tok == Token::RBRACE || 3364 tok == Token::RBRACE ||
3329 tok == Token::EOS) { 3365 tok == Token::EOS) {
3330 return; 3366 return;
3331 } 3367 }
3332 Expect(Token::SEMICOLON, ok); 3368 Expect(Token::SEMICOLON, ok);
3333 } 3369 }
3334 3370
3335 3371
3336 Literal* Parser::GetLiteralUndefined() { 3372 Literal* Parser::GetLiteralUndefined() {
3337 return new Literal(Factory::undefined_value()); 3373 return new Literal(Factory::undefined_value());
(...skipping 30 matching lines...) Expand all
3368 3404
3369 // This function reads an identifier and determines whether or not it 3405 // This function reads an identifier and determines whether or not it
3370 // is 'get' or 'set'. The reason for not using ParseIdentifier and 3406 // is 'get' or 'set'. The reason for not using ParseIdentifier and
3371 // checking on the output is that this involves heap allocation which 3407 // checking on the output is that this involves heap allocation which
3372 // we can't do during preparsing. 3408 // we can't do during preparsing.
3373 Handle<String> Parser::ParseIdentifierOrGetOrSet(bool* is_get, 3409 Handle<String> Parser::ParseIdentifierOrGetOrSet(bool* is_get,
3374 bool* is_set, 3410 bool* is_set,
3375 bool* ok) { 3411 bool* ok) {
3376 Expect(Token::IDENTIFIER, ok); 3412 Expect(Token::IDENTIFIER, ok);
3377 if (!*ok) return Handle<String>(); 3413 if (!*ok) return Handle<String>();
3378 if (scanner_.literal_length() == 3) { 3414 if (scanner().literal_length() == 3) {
3379 const char* token = scanner_.literal_string(); 3415 const char* token = scanner().literal_string();
3380 *is_get = strcmp(token, "get") == 0; 3416 *is_get = strcmp(token, "get") == 0;
3381 *is_set = !*is_get && strcmp(token, "set") == 0; 3417 *is_set = !*is_get && strcmp(token, "set") == 0;
3382 } 3418 }
3383 return GetSymbol(ok); 3419 return GetSymbol(ok);
3384 } 3420 }
3385 3421
3386 3422
3387 // ---------------------------------------------------------------------------- 3423 // ----------------------------------------------------------------------------
3388 // Parser support 3424 // Parser support
3389 3425
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after
3488 ZoneList<Expression*>* args = new ZoneList<Expression*>(2); 3524 ZoneList<Expression*>* args = new ZoneList<Expression*>(2);
3489 args->Add(new Literal(type)); 3525 args->Add(new Literal(type));
3490 args->Add(new Literal(array)); 3526 args->Add(new Literal(array));
3491 return new Throw(new CallRuntime(constructor, NULL, args), 3527 return new Throw(new CallRuntime(constructor, NULL, args),
3492 scanner().location().beg_pos); 3528 scanner().location().beg_pos);
3493 } 3529 }
3494 3530
3495 // ---------------------------------------------------------------------------- 3531 // ----------------------------------------------------------------------------
3496 // JSON 3532 // JSON
3497 3533
3498 Handle<Object> JsonParser::ParseJson(Handle<String> source) { 3534 Handle<Object> JsonParser::ParseJson(Handle<String> script,
3499 source->TryFlatten(); 3535 UC16CharacterStream* source) {
3500 scanner_.Initialize(source); 3536 scanner_.Initialize(source);
3501 stack_overflow_ = false; 3537 stack_overflow_ = false;
3502 Handle<Object> result = ParseJsonValue(); 3538 Handle<Object> result = ParseJsonValue();
3503 if (result.is_null() || scanner_.Next() != Token::EOS) { 3539 if (result.is_null() || scanner_.Next() != Token::EOS) {
3504 if (stack_overflow_) { 3540 if (stack_overflow_) {
3505 // Scanner failed. 3541 // Scanner failed.
3506 Top::StackOverflow(); 3542 Top::StackOverflow();
3507 } else { 3543 } else {
3508 // Parse failed. Scanner's current token is the unexpected token. 3544 // Parse failed. Scanner's current token is the unexpected token.
3509 Token::Value token = scanner_.current_token(); 3545 Token::Value token = scanner_.current_token();
(...skipping 15 matching lines...) Expand all
3525 message = "unexpected_token_identifier"; 3561 message = "unexpected_token_identifier";
3526 break; 3562 break;
3527 default: 3563 default:
3528 message = "unexpected_token"; 3564 message = "unexpected_token";
3529 name_opt = Token::String(token); 3565 name_opt = Token::String(token);
3530 ASSERT(name_opt != NULL); 3566 ASSERT(name_opt != NULL);
3531 break; 3567 break;
3532 } 3568 }
3533 3569
3534 Scanner::Location source_location = scanner_.location(); 3570 Scanner::Location source_location = scanner_.location();
3535 MessageLocation location(Factory::NewScript(source), 3571 MessageLocation location(Factory::NewScript(script),
3536 source_location.beg_pos, 3572 source_location.beg_pos,
3537 source_location.end_pos); 3573 source_location.end_pos);
3538 int argc = (name_opt == NULL) ? 0 : 1; 3574 int argc = (name_opt == NULL) ? 0 : 1;
3539 Handle<JSArray> array = Factory::NewJSArray(argc); 3575 Handle<JSArray> array = Factory::NewJSArray(argc);
3540 if (name_opt != NULL) { 3576 if (name_opt != NULL) {
3541 SetElement(array, 3577 SetElement(array,
3542 0, 3578 0,
3543 Factory::NewStringFromUtf8(CStrVector(name_opt))); 3579 Factory::NewStringFromUtf8(CStrVector(name_opt)));
3544 } 3580 }
3545 Handle<Object> result = Factory::NewSyntaxError(message, array); 3581 Handle<Object> result = Factory::NewSyntaxError(message, array);
(...skipping 994 matching lines...) Expand 10 before | Expand all | Expand 10 after
4540 input = *data; 4576 input = *data;
4541 result = (result << 7) | (input & 0x7f); 4577 result = (result << 7) | (input & 0x7f);
4542 data++; 4578 data++;
4543 } 4579 }
4544 *source = data; 4580 *source = data;
4545 return result; 4581 return result;
4546 } 4582 }
4547 4583
4548 4584
4549 // Create a Scanner for the preparser to use as input, and preparse the source. 4585 // Create a Scanner for the preparser to use as input, and preparse the source.
4550 static ScriptDataImpl* DoPreParse(Handle<String> source, 4586 static ScriptDataImpl* DoPreParse(UC16CharacterStream* source,
4551 unibrow::CharacterStream* stream,
4552 bool allow_lazy, 4587 bool allow_lazy,
4553 ParserRecorder* recorder, 4588 ParserRecorder* recorder,
4554 int literal_flags) { 4589 int literal_flags) {
4555 V8JavaScriptScanner scanner; 4590 V8JavaScriptScanner scanner;
4556 scanner.Initialize(source, stream, literal_flags); 4591 scanner.Initialize(source, literal_flags);
4557 intptr_t stack_limit = StackGuard::real_climit(); 4592 intptr_t stack_limit = StackGuard::real_climit();
4558 if (!preparser::PreParser::PreParseProgram(&scanner, 4593 if (!preparser::PreParser::PreParseProgram(&scanner,
4559 recorder, 4594 recorder,
4560 allow_lazy, 4595 allow_lazy,
4561 stack_limit)) { 4596 stack_limit)) {
4562 Top::StackOverflow(); 4597 Top::StackOverflow();
4563 return NULL; 4598 return NULL;
4564 } 4599 }
4565 4600
4566 // Extract the accumulated data from the recorder as a single 4601 // Extract the accumulated data from the recorder as a single
4567 // contiguous vector that we are responsible for disposing. 4602 // contiguous vector that we are responsible for disposing.
4568 Vector<unsigned> store = recorder->ExtractData(); 4603 Vector<unsigned> store = recorder->ExtractData();
4569 return new ScriptDataImpl(store); 4604 return new ScriptDataImpl(store);
4570 } 4605 }
4571 4606
4572 4607
4573 // Preparse, but only collect data that is immediately useful, 4608 // Preparse, but only collect data that is immediately useful,
4574 // even if the preparser data is only used once. 4609 // even if the preparser data is only used once.
4575 ScriptDataImpl* ParserApi::PartialPreParse(Handle<String> source, 4610 ScriptDataImpl* ParserApi::PartialPreParse(UC16CharacterStream* source,
4576 unibrow::CharacterStream* stream,
4577 v8::Extension* extension) { 4611 v8::Extension* extension) {
4578 bool allow_lazy = FLAG_lazy && (extension == NULL); 4612 bool allow_lazy = FLAG_lazy && (extension == NULL);
4579 if (!allow_lazy) { 4613 if (!allow_lazy) {
4580 // Partial preparsing is only about lazily compiled functions. 4614 // Partial preparsing is only about lazily compiled functions.
4581 // If we don't allow lazy compilation, the log data will be empty. 4615 // If we don't allow lazy compilation, the log data will be empty.
4582 return NULL; 4616 return NULL;
4583 } 4617 }
4584 PartialParserRecorder recorder; 4618 PartialParserRecorder recorder;
4585 4619 return DoPreParse(source, allow_lazy, &recorder,
4586 return DoPreParse(source, stream, allow_lazy, &recorder,
4587 JavaScriptScanner::kNoLiterals); 4620 JavaScriptScanner::kNoLiterals);
4588 } 4621 }
4589 4622
4590 4623
4591 ScriptDataImpl* ParserApi::PreParse(Handle<String> source, 4624 ScriptDataImpl* ParserApi::PreParse(UC16CharacterStream* source,
4592 unibrow::CharacterStream* stream,
4593 v8::Extension* extension) { 4625 v8::Extension* extension) {
4594 Handle<Script> no_script; 4626 Handle<Script> no_script;
4595 bool allow_lazy = FLAG_lazy && (extension == NULL); 4627 bool allow_lazy = FLAG_lazy && (extension == NULL);
4596 CompleteParserRecorder recorder; 4628 CompleteParserRecorder recorder;
4597 int kPreParseLiteralsFlags = 4629 int kPreParseLiteralsFlags =
4598 JavaScriptScanner::kLiteralString | JavaScriptScanner::kLiteralIdentifier; 4630 JavaScriptScanner::kLiteralString | JavaScriptScanner::kLiteralIdentifier;
4599 return DoPreParse(source, stream, allow_lazy, 4631 return DoPreParse(source, allow_lazy, &recorder, kPreParseLiteralsFlags);
4600 &recorder, kPreParseLiteralsFlags);
4601 } 4632 }
4602 4633
4603 4634
4604 bool RegExpParser::ParseRegExp(FlatStringReader* input, 4635 bool RegExpParser::ParseRegExp(FlatStringReader* input,
4605 bool multiline, 4636 bool multiline,
4606 RegExpCompileData* result) { 4637 RegExpCompileData* result) {
4607 ASSERT(result != NULL); 4638 ASSERT(result != NULL);
4608 RegExpParser parser(input, &result->error, multiline); 4639 RegExpParser parser(input, &result->error, multiline);
4609 RegExpTree* tree = parser.ParsePattern(); 4640 RegExpTree* tree = parser.ParsePattern();
4610 if (parser.failed()) { 4641 if (parser.failed()) {
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
4650 Handle<String> source = Handle<String>(String::cast(script->source())); 4681 Handle<String> source = Handle<String>(String::cast(script->source()));
4651 result = parser.ParseProgram(source, info->is_global()); 4682 result = parser.ParseProgram(source, info->is_global());
4652 } 4683 }
4653 } 4684 }
4654 4685
4655 info->SetFunction(result); 4686 info->SetFunction(result);
4656 return (result != NULL); 4687 return (result != NULL);
4657 } 4688 }
4658 4689
4659 } } // namespace v8::internal 4690 } } // namespace v8::internal
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698