| Index: src/parser.cc
|
| diff --git a/src/parser.cc b/src/parser.cc
|
| index 94ad57c9c28ba02a40b111562c56aa1f243129b1..056332b5b44ec8de7049aa392daa1ddda57e0ebb 100644
|
| --- a/src/parser.cc
|
| +++ b/src/parser.cc
|
| @@ -609,25 +609,7 @@ FunctionLiteral* Parser::ParseProgram(Handle<String> source,
|
|
|
| // Initialize parser state.
|
| source->TryFlatten();
|
| - if (source->IsExternalTwoByteString()) {
|
| - // Notice that the stream is destroyed at the end of the branch block.
|
| - // The last line of the blocks can't be moved outside, even though they're
|
| - // identical calls.
|
| - ExternalTwoByteStringUC16CharacterStream stream(
|
| - Handle<ExternalTwoByteString>::cast(source), 0, source->length());
|
| - scanner_.Initialize(&stream, JavaScriptScanner::kAllLiterals);
|
| - return DoParseProgram(source, in_global_context, &zone_scope);
|
| - } else {
|
| - GenericStringUC16CharacterStream stream(source, 0, source->length());
|
| - scanner_.Initialize(&stream, JavaScriptScanner::kAllLiterals);
|
| - return DoParseProgram(source, in_global_context, &zone_scope);
|
| - }
|
| -}
|
| -
|
| -
|
| -FunctionLiteral* Parser::DoParseProgram(Handle<String> source,
|
| - bool in_global_context,
|
| - ZoneScope* zone_scope) {
|
| + scanner_.Initialize(source);
|
| ASSERT(target_stack_ == NULL);
|
| if (pre_data_ != NULL) pre_data_->Initialize();
|
|
|
| @@ -673,45 +655,25 @@ FunctionLiteral* Parser::DoParseProgram(Handle<String> source,
|
|
|
| // If there was a syntax error we have to get rid of the AST
|
| // and it is not safe to do so before the scope has been deleted.
|
| - if (result == NULL) zone_scope->DeleteOnExit();
|
| + if (result == NULL) zone_scope.DeleteOnExit();
|
| return result;
|
| }
|
|
|
| +
|
| FunctionLiteral* Parser::ParseLazy(Handle<SharedFunctionInfo> info) {
|
| CompilationZoneScope zone_scope(DONT_DELETE_ON_EXIT);
|
| HistogramTimerScope timer(&Counters::parse_lazy);
|
| Handle<String> source(String::cast(script_->source()));
|
| Counters::total_parse_size.Increment(source->length());
|
|
|
| - // Initialize parser state.
|
| - source->TryFlatten();
|
| - if (source->IsExternalTwoByteString()) {
|
| - ExternalTwoByteStringUC16CharacterStream stream(
|
| - Handle<ExternalTwoByteString>::cast(source),
|
| - info->start_position(),
|
| - info->end_position());
|
| - FunctionLiteral* result = ParseLazy(info, &stream, &zone_scope);
|
| - return result;
|
| - } else {
|
| - GenericStringUC16CharacterStream stream(source,
|
| - info->start_position(),
|
| - info->end_position());
|
| - FunctionLiteral* result = ParseLazy(info, &stream, &zone_scope);
|
| - return result;
|
| - }
|
| -}
|
| -
|
| -
|
| -FunctionLiteral* Parser::ParseLazy(Handle<SharedFunctionInfo> info,
|
| - UC16CharacterStream* source,
|
| - ZoneScope* zone_scope) {
|
| - scanner_.Initialize(source, JavaScriptScanner::kAllLiterals);
|
| - ASSERT(target_stack_ == NULL);
|
| -
|
| Handle<String> name(String::cast(info->name()));
|
| fni_ = new FuncNameInferrer();
|
| fni_->PushEnclosingName(name);
|
|
|
| + // Initialize parser state.
|
| + source->TryFlatten();
|
| + scanner_.Initialize(source, info->start_position(), info->end_position());
|
| + ASSERT(target_stack_ == NULL);
|
| mode_ = PARSE_EAGERLY;
|
|
|
| // Place holder for the result.
|
| @@ -743,7 +705,7 @@ FunctionLiteral* Parser::ParseLazy(Handle<SharedFunctionInfo> info,
|
| // not safe to do before scope has been deleted.
|
| if (result == NULL) {
|
| Top::StackOverflow();
|
| - zone_scope->DeleteOnExit();
|
| + zone_scope.DeleteOnExit();
|
| } else {
|
| Handle<String> inferred_name(info->inferred_name());
|
| result->set_inferred_name(inferred_name);
|
| @@ -757,12 +719,12 @@ Handle<String> Parser::GetSymbol(bool* ok) {
|
| if (pre_data() != NULL) {
|
| symbol_id = pre_data()->GetSymbolIdentifier();
|
| }
|
| - return LookupSymbol(symbol_id, scanner().literal());
|
| + return LookupSymbol(symbol_id, scanner_.literal());
|
| }
|
|
|
|
|
| void Parser::ReportMessage(const char* type, Vector<const char*> args) {
|
| - Scanner::Location source_location = scanner().location();
|
| + Scanner::Location source_location = scanner_.location();
|
| ReportMessageAt(source_location, type, args);
|
| }
|
|
|
| @@ -1679,7 +1641,7 @@ Statement* Parser::ParseContinueStatement(bool* ok) {
|
| Expect(Token::CONTINUE, CHECK_OK);
|
| Handle<String> label = Handle<String>::null();
|
| Token::Value tok = peek();
|
| - if (!scanner().has_line_terminator_before_next() &&
|
| + if (!scanner_.has_line_terminator_before_next() &&
|
| tok != Token::SEMICOLON && tok != Token::RBRACE && tok != Token::EOS) {
|
| label = ParseIdentifier(CHECK_OK);
|
| }
|
| @@ -1705,7 +1667,7 @@ Statement* Parser::ParseBreakStatement(ZoneStringList* labels, bool* ok) {
|
| Expect(Token::BREAK, CHECK_OK);
|
| Handle<String> label;
|
| Token::Value tok = peek();
|
| - if (!scanner().has_line_terminator_before_next() &&
|
| + if (!scanner_.has_line_terminator_before_next() &&
|
| tok != Token::SEMICOLON && tok != Token::RBRACE && tok != Token::EOS) {
|
| label = ParseIdentifier(CHECK_OK);
|
| }
|
| @@ -1750,7 +1712,7 @@ Statement* Parser::ParseReturnStatement(bool* ok) {
|
| }
|
|
|
| Token::Value tok = peek();
|
| - if (scanner().has_line_terminator_before_next() ||
|
| + if (scanner_.has_line_terminator_before_next() ||
|
| tok == Token::SEMICOLON ||
|
| tok == Token::RBRACE ||
|
| tok == Token::EOS) {
|
| @@ -1882,7 +1844,7 @@ Statement* Parser::ParseThrowStatement(bool* ok) {
|
|
|
| Expect(Token::THROW, CHECK_OK);
|
| int pos = scanner().location().beg_pos;
|
| - if (scanner().has_line_terminator_before_next()) {
|
| + if (scanner_.has_line_terminator_before_next()) {
|
| ReportMessage("newline_after_throw", Vector<const char*>::empty());
|
| *ok = false;
|
| return NULL;
|
| @@ -2446,8 +2408,7 @@ Expression* Parser::ParsePostfixExpression(bool* ok) {
|
| // LeftHandSideExpression ('++' | '--')?
|
|
|
| Expression* expression = ParseLeftHandSideExpression(CHECK_OK);
|
| - if (!scanner().has_line_terminator_before_next() &&
|
| - Token::IsCountOp(peek())) {
|
| + if (!scanner_.has_line_terminator_before_next() && Token::IsCountOp(peek())) {
|
| // Signal a reference error if the expression is an invalid
|
| // left-hand side expression. We could report this as a syntax
|
| // error here but for compatibility with JSC we choose to report the
|
| @@ -2716,7 +2677,7 @@ Expression* Parser::ParsePrimaryExpression(bool* ok) {
|
| case Token::NUMBER: {
|
| Consume(Token::NUMBER);
|
| double value =
|
| - StringToDouble(scanner().literal(), ALLOW_HEX | ALLOW_OCTALS);
|
| + StringToDouble(scanner_.literal(), ALLOW_HEX | ALLOW_OCTALS);
|
| result = NewNumberLiteral(value);
|
| break;
|
| }
|
| @@ -3067,7 +3028,7 @@ Expression* Parser::ParseObjectLiteral(bool* ok) {
|
| case Token::NUMBER: {
|
| Consume(Token::NUMBER);
|
| double value =
|
| - StringToDouble(scanner().literal(), ALLOW_HEX | ALLOW_OCTALS);
|
| + StringToDouble(scanner_.literal(), ALLOW_HEX | ALLOW_OCTALS);
|
| key = NewNumberLiteral(value);
|
| break;
|
| }
|
| @@ -3128,7 +3089,7 @@ Expression* Parser::ParseObjectLiteral(bool* ok) {
|
|
|
|
|
| Expression* Parser::ParseRegExpLiteral(bool seen_equal, bool* ok) {
|
| - if (!scanner().ScanRegExpPattern(seen_equal)) {
|
| + if (!scanner_.ScanRegExpPattern(seen_equal)) {
|
| Next();
|
| ReportMessage("unterminated_regexp", Vector<const char*>::empty());
|
| *ok = false;
|
| @@ -3138,10 +3099,10 @@ Expression* Parser::ParseRegExpLiteral(bool seen_equal, bool* ok) {
|
| int literal_index = temp_scope_->NextMaterializedLiteralIndex();
|
|
|
| Handle<String> js_pattern =
|
| - Factory::NewStringFromUtf8(scanner().next_literal(), TENURED);
|
| - scanner().ScanRegExpFlags();
|
| + Factory::NewStringFromUtf8(scanner_.next_literal(), TENURED);
|
| + scanner_.ScanRegExpFlags();
|
| Handle<String> js_flags =
|
| - Factory::NewStringFromUtf8(scanner().next_literal(), TENURED);
|
| + Factory::NewStringFromUtf8(scanner_.next_literal(), TENURED);
|
| Next();
|
|
|
| return new RegExpLiteral(js_pattern, js_flags, literal_index);
|
| @@ -3197,7 +3158,7 @@ FunctionLiteral* Parser::ParseFunctionLiteral(Handle<String> var_name,
|
| // FormalParameterList ::
|
| // '(' (Identifier)*[','] ')'
|
| Expect(Token::LPAREN, CHECK_OK);
|
| - int start_pos = scanner().location().beg_pos;
|
| + int start_pos = scanner_.location().beg_pos;
|
| bool done = (peek() == Token::RPAREN);
|
| while (!done) {
|
| Handle<String> param_name = ParseIdentifier(CHECK_OK);
|
| @@ -3234,7 +3195,7 @@ FunctionLiteral* Parser::ParseFunctionLiteral(Handle<String> var_name,
|
| bool is_lazily_compiled =
|
| mode() == PARSE_LAZILY && top_scope_->HasTrivialOuterContext();
|
|
|
| - int function_block_pos = scanner().location().beg_pos;
|
| + int function_block_pos = scanner_.location().beg_pos;
|
| int materialized_literal_count;
|
| int expected_property_count;
|
| int end_pos;
|
| @@ -3251,8 +3212,7 @@ FunctionLiteral* Parser::ParseFunctionLiteral(Handle<String> var_name,
|
| ReportInvalidPreparseData(name, CHECK_OK);
|
| }
|
| Counters::total_preparse_skipped.Increment(end_pos - function_block_pos);
|
| - // Seek to position just before terminal '}'.
|
| - scanner().SeekForward(end_pos - 1);
|
| + scanner_.SeekForward(end_pos);
|
| materialized_literal_count = entry.literal_count();
|
| expected_property_count = entry.property_count();
|
| only_simple_this_property_assignments = false;
|
| @@ -3268,7 +3228,7 @@ FunctionLiteral* Parser::ParseFunctionLiteral(Handle<String> var_name,
|
| this_property_assignments = temp_scope.this_property_assignments();
|
|
|
| Expect(Token::RBRACE, CHECK_OK);
|
| - end_pos = scanner().location().end_pos;
|
| + end_pos = scanner_.location().end_pos;
|
| }
|
|
|
| FunctionLiteral* function_literal =
|
| @@ -3372,7 +3332,7 @@ void Parser::ExpectSemicolon(bool* ok) {
|
| Next();
|
| return;
|
| }
|
| - if (scanner().has_line_terminator_before_next() ||
|
| + if (scanner_.has_line_terminator_before_next() ||
|
| tok == Token::RBRACE ||
|
| tok == Token::EOS) {
|
| return;
|
| @@ -3423,8 +3383,8 @@ Handle<String> Parser::ParseIdentifierOrGetOrSet(bool* is_get,
|
| bool* ok) {
|
| Expect(Token::IDENTIFIER, ok);
|
| if (!*ok) return Handle<String>();
|
| - if (scanner().literal_length() == 3) {
|
| - const char* token = scanner().literal_string();
|
| + if (scanner_.literal_length() == 3) {
|
| + const char* token = scanner_.literal_string();
|
| *is_get = strcmp(token, "get") == 0;
|
| *is_set = !*is_get && strcmp(token, "set") == 0;
|
| }
|
| @@ -3543,8 +3503,8 @@ Expression* Parser::NewThrowError(Handle<String> constructor,
|
| // ----------------------------------------------------------------------------
|
| // JSON
|
|
|
| -Handle<Object> JsonParser::ParseJson(Handle<String> script,
|
| - UC16CharacterStream* source) {
|
| +Handle<Object> JsonParser::ParseJson(Handle<String> source) {
|
| + source->TryFlatten();
|
| scanner_.Initialize(source);
|
| stack_overflow_ = false;
|
| Handle<Object> result = ParseJsonValue();
|
| @@ -3580,7 +3540,7 @@ Handle<Object> JsonParser::ParseJson(Handle<String> script,
|
| }
|
|
|
| Scanner::Location source_location = scanner_.location();
|
| - MessageLocation location(Factory::NewScript(script),
|
| + MessageLocation location(Factory::NewScript(source),
|
| source_location.beg_pos,
|
| source_location.end_pos);
|
| int argc = (name_opt == NULL) ? 0 : 1;
|
| @@ -4449,25 +4409,10 @@ CharacterRange RegExpParser::ParseClassAtom(uc16* char_class) {
|
| }
|
|
|
|
|
| -static const uc16 kNoCharClass = 0;
|
| -
|
| -// Adds range or pre-defined character class to character ranges.
|
| -// If char_class is not kInvalidClass, it's interpreted as a class
|
| -// escape (i.e., 's' means whitespace, from '\s').
|
| -static inline void AddRangeOrEscape(ZoneList<CharacterRange>* ranges,
|
| - uc16 char_class,
|
| - CharacterRange range) {
|
| - if (char_class != kNoCharClass) {
|
| - CharacterRange::AddClassEscape(char_class, ranges);
|
| - } else {
|
| - ranges->Add(range);
|
| - }
|
| -}
|
| -
|
| -
|
| RegExpTree* RegExpParser::ParseCharacterClass() {
|
| static const char* kUnterminated = "Unterminated character class";
|
| static const char* kRangeOutOfOrder = "Range out of order in character class";
|
| + static const char* kInvalidRange = "Invalid character range";
|
|
|
| ASSERT_EQ(current(), '[');
|
| Advance();
|
| @@ -4476,10 +4421,30 @@ RegExpTree* RegExpParser::ParseCharacterClass() {
|
| is_negated = true;
|
| Advance();
|
| }
|
| + // A CharacterClass is a sequence of single characters, character class
|
| + // escapes or ranges. Ranges are on the form "x-y" where x and y are
|
| + // single characters (and not character class escapes like \s).
|
| + // A "-" may occur at the start or end of the character class (just after
|
| + // "[" or "[^", or just before "]") without being considered part of a
|
| + // range. A "-" may also appear as the beginning or end of a range.
|
| + // I.e., [--+] is valid, so is [!--].
|
| +
|
| ZoneList<CharacterRange>* ranges = new ZoneList<CharacterRange>(2);
|
| while (has_more() && current() != ']') {
|
| - uc16 char_class = kNoCharClass;
|
| + uc16 char_class = 0;
|
| CharacterRange first = ParseClassAtom(&char_class CHECK_FAILED);
|
| + if (char_class) {
|
| + CharacterRange::AddClassEscape(char_class, ranges);
|
| + if (current() == '-') {
|
| + Advance();
|
| + ranges->Add(CharacterRange::Singleton('-'));
|
| + if (current() != ']') {
|
| + ReportError(CStrVector(kInvalidRange) CHECK_FAILED);
|
| + }
|
| + break;
|
| + }
|
| + continue;
|
| + }
|
| if (current() == '-') {
|
| Advance();
|
| if (current() == kEndMarker) {
|
| @@ -4487,25 +4452,20 @@ RegExpTree* RegExpParser::ParseCharacterClass() {
|
| // following code report an error.
|
| break;
|
| } else if (current() == ']') {
|
| - AddRangeOrEscape(ranges, char_class, first);
|
| + ranges->Add(first);
|
| ranges->Add(CharacterRange::Singleton('-'));
|
| break;
|
| }
|
| - uc16 char_class_2 = kNoCharClass;
|
| - CharacterRange next = ParseClassAtom(&char_class_2 CHECK_FAILED);
|
| - if (char_class != kNoCharClass || char_class_2 != kNoCharClass) {
|
| - // Either end is an escaped character class. Treat the '-' verbatim.
|
| - AddRangeOrEscape(ranges, char_class, first);
|
| - ranges->Add(CharacterRange::Singleton('-'));
|
| - AddRangeOrEscape(ranges, char_class_2, next);
|
| - continue;
|
| + CharacterRange next = ParseClassAtom(&char_class CHECK_FAILED);
|
| + if (char_class) {
|
| + ReportError(CStrVector(kInvalidRange) CHECK_FAILED);
|
| }
|
| if (first.from() > next.to()) {
|
| return ReportError(CStrVector(kRangeOutOfOrder) CHECK_FAILED);
|
| }
|
| ranges->Add(CharacterRange::Range(first.from(), next.to()));
|
| } else {
|
| - AddRangeOrEscape(ranges, char_class, first);
|
| + ranges->Add(first);
|
| }
|
| }
|
| if (!has_more()) {
|
| @@ -4595,12 +4555,13 @@ int ScriptDataImpl::ReadNumber(byte** source) {
|
|
|
|
|
| // Create a Scanner for the preparser to use as input, and preparse the source.
|
| -static ScriptDataImpl* DoPreParse(UC16CharacterStream* source,
|
| +static ScriptDataImpl* DoPreParse(Handle<String> source,
|
| + unibrow::CharacterStream* stream,
|
| bool allow_lazy,
|
| ParserRecorder* recorder,
|
| int literal_flags) {
|
| V8JavaScriptScanner scanner;
|
| - scanner.Initialize(source, literal_flags);
|
| + scanner.Initialize(source, stream, literal_flags);
|
| intptr_t stack_limit = StackGuard::real_climit();
|
| if (!preparser::PreParser::PreParseProgram(&scanner,
|
| recorder,
|
| @@ -4619,7 +4580,8 @@ static ScriptDataImpl* DoPreParse(UC16CharacterStream* source,
|
|
|
| // Preparse, but only collect data that is immediately useful,
|
| // even if the preparser data is only used once.
|
| -ScriptDataImpl* ParserApi::PartialPreParse(UC16CharacterStream* source,
|
| +ScriptDataImpl* ParserApi::PartialPreParse(Handle<String> source,
|
| + unibrow::CharacterStream* stream,
|
| v8::Extension* extension) {
|
| bool allow_lazy = FLAG_lazy && (extension == NULL);
|
| if (!allow_lazy) {
|
| @@ -4628,19 +4590,22 @@ ScriptDataImpl* ParserApi::PartialPreParse(UC16CharacterStream* source,
|
| return NULL;
|
| }
|
| PartialParserRecorder recorder;
|
| - return DoPreParse(source, allow_lazy, &recorder,
|
| +
|
| + return DoPreParse(source, stream, allow_lazy, &recorder,
|
| JavaScriptScanner::kNoLiterals);
|
| }
|
|
|
|
|
| -ScriptDataImpl* ParserApi::PreParse(UC16CharacterStream* source,
|
| +ScriptDataImpl* ParserApi::PreParse(Handle<String> source,
|
| + unibrow::CharacterStream* stream,
|
| v8::Extension* extension) {
|
| Handle<Script> no_script;
|
| bool allow_lazy = FLAG_lazy && (extension == NULL);
|
| CompleteParserRecorder recorder;
|
| int kPreParseLiteralsFlags =
|
| JavaScriptScanner::kLiteralString | JavaScriptScanner::kLiteralIdentifier;
|
| - return DoPreParse(source, allow_lazy, &recorder, kPreParseLiteralsFlags);
|
| + return DoPreParse(source, stream, allow_lazy,
|
| + &recorder, kPreParseLiteralsFlags);
|
| }
|
|
|
|
|
|
|