diff options
author | Fedor Indutny <fedor@indutny.com> | 2014-10-10 14:49:02 +0400 |
---|---|---|
committer | Fedor Indutny <fedor@indutny.com> | 2014-10-10 14:49:02 +0400 |
commit | 6bcea4ff932144a5fd02affefd45164fbf471e67 (patch) | |
tree | a8e078c679b12f0daebe10ed254239cb0d79e146 /deps/v8/src/parser.cc | |
parent | 4fae2356d105e394115188a814097c4a95ae0c5d (diff) | |
download | node-new-6bcea4ff932144a5fd02affefd45164fbf471e67.tar.gz |
deps: update v8 to 3.29.93.1
Diffstat (limited to 'deps/v8/src/parser.cc')
-rw-r--r-- | deps/v8/src/parser.cc | 513 |
1 files changed, 333 insertions, 180 deletions
diff --git a/deps/v8/src/parser.cc b/deps/v8/src/parser.cc index 6c941daa97..9d1a40d39b 100644 --- a/deps/v8/src/parser.cc +++ b/deps/v8/src/parser.cc @@ -6,6 +6,7 @@ #include "src/api.h" #include "src/ast.h" +#include "src/bailout-reason.h" #include "src/base/platform/platform.h" #include "src/bootstrapper.h" #include "src/char-predicates-inl.h" @@ -14,7 +15,7 @@ #include "src/messages.h" #include "src/parser.h" #include "src/preparser.h" -#include "src/runtime.h" +#include "src/runtime/runtime.h" #include "src/scanner-character-streams.h" #include "src/scopeinfo.h" #include "src/string-stream.h" @@ -266,9 +267,9 @@ void Parser::SetCachedData() { Scope* Parser::NewScope(Scope* parent, ScopeType scope_type) { - DCHECK(ast_value_factory_); + DCHECK(ast_value_factory()); Scope* result = - new (zone()) Scope(parent, scope_type, ast_value_factory_, zone()); + new (zone()) Scope(parent, scope_type, ast_value_factory(), zone()); result->Initialize(); return result; } @@ -341,9 +342,38 @@ class TargetScope BASE_EMBEDDED { // ---------------------------------------------------------------------------- // Implementation of Parser +class ParserTraits::Checkpoint + : public ParserBase<ParserTraits>::CheckpointBase { + public: + explicit Checkpoint(ParserBase<ParserTraits>* parser) + : CheckpointBase(parser), parser_(parser) { + saved_ast_node_id_gen_ = *parser_->ast_node_id_gen_; + } + + void Restore() { + CheckpointBase::Restore(); + *parser_->ast_node_id_gen_ = saved_ast_node_id_gen_; + } + + private: + ParserBase<ParserTraits>* parser_; + AstNode::IdGen saved_ast_node_id_gen_; +}; + + bool ParserTraits::IsEvalOrArguments(const AstRawString* identifier) const { - return identifier == parser_->ast_value_factory_->eval_string() || - identifier == parser_->ast_value_factory_->arguments_string(); + return identifier == parser_->ast_value_factory()->eval_string() || + identifier == parser_->ast_value_factory()->arguments_string(); +} + + +bool ParserTraits::IsPrototype(const AstRawString* identifier) const { + return identifier == parser_->ast_value_factory()->prototype_string(); +} + + +bool ParserTraits::IsConstructor(const AstRawString* identifier) const { + return identifier == parser_->ast_value_factory()->constructor_string(); } @@ -368,7 +398,7 @@ void ParserTraits::PushPropertyName(FuncNameInferrer* fni, fni->PushLiteralName(expression->AsLiteral()->AsRawPropertyName()); } else { fni->PushLiteralName( - parser_->ast_value_factory_->anonymous_function_string()); + parser_->ast_value_factory()->anonymous_function_string()); } } @@ -387,7 +417,7 @@ void ParserTraits::CheckPossibleEvalCall(Expression* expression, Scope* scope) { VariableProxy* callee = expression->AsVariableProxy(); if (callee != NULL && - callee->raw_name() == parser_->ast_value_factory_->eval_string()) { + callee->raw_name() == parser_->ast_value_factory()->eval_string()) { scope->DeclarationScope()->RecordEvalCall(); } } @@ -507,21 +537,21 @@ Expression* ParserTraits::BuildUnaryExpression( Expression* ParserTraits::NewThrowReferenceError(const char* message, int pos) { return NewThrowError( - parser_->ast_value_factory_->make_reference_error_string(), message, NULL, - pos); + parser_->ast_value_factory()->make_reference_error_string(), message, + NULL, pos); } Expression* ParserTraits::NewThrowSyntaxError( const char* message, const AstRawString* arg, int pos) { - return NewThrowError(parser_->ast_value_factory_->make_syntax_error_string(), + return NewThrowError(parser_->ast_value_factory()->make_syntax_error_string(), message, arg, pos); } Expression* ParserTraits::NewThrowTypeError( const char* message, const AstRawString* arg, int pos) { - return NewThrowError(parser_->ast_value_factory_->make_type_error_string(), + return NewThrowError(parser_->ast_value_factory()->make_type_error_string(), message, arg, pos); } @@ -532,7 +562,7 @@ Expression* ParserTraits::NewThrowError( Zone* zone = parser_->zone(); int argc = arg != NULL ? 1 : 0; const AstRawString* type = - parser_->ast_value_factory_->GetOneByteString(message); + parser_->ast_value_factory()->GetOneByteString(message); ZoneList<const AstRawString*>* array = new (zone) ZoneList<const AstRawString*>(argc, zone); if (arg != NULL) { @@ -603,14 +633,23 @@ void ParserTraits::ReportMessageAt(Scanner::Location source_location, const AstRawString* ParserTraits::GetSymbol(Scanner* scanner) { const AstRawString* result = - parser_->scanner()->CurrentSymbol(parser_->ast_value_factory_); + parser_->scanner()->CurrentSymbol(parser_->ast_value_factory()); DCHECK(result != NULL); return result; } +const AstRawString* ParserTraits::GetNumberAsSymbol(Scanner* scanner) { + double double_value = parser_->scanner()->DoubleValue(); + char array[100]; + const char* string = + DoubleToCString(double_value, Vector<char>(array, arraysize(array))); + return ast_value_factory()->GetOneByteString(string); +} + + const AstRawString* ParserTraits::GetNextSymbol(Scanner* scanner) { - return parser_->scanner()->NextSymbol(parser_->ast_value_factory_); + return parser_->scanner()->NextSymbol(parser_->ast_value_factory()); } @@ -619,6 +658,19 @@ Expression* ParserTraits::ThisExpression( return factory->NewVariableProxy(scope->receiver(), pos); } +Expression* ParserTraits::SuperReference( + Scope* scope, AstNodeFactory<AstConstructionVisitor>* factory, int pos) { + return factory->NewSuperReference( + ThisExpression(scope, factory, pos)->AsVariableProxy(), + pos); +} + +Expression* ParserTraits::ClassLiteral( + const AstRawString* name, Expression* extends, Expression* constructor, + ZoneList<ObjectLiteral::Property*>* properties, int pos, + AstNodeFactory<AstConstructionVisitor>* factory) { + return factory->NewClassLiteral(name, extends, constructor, properties, pos); +} Literal* ParserTraits::ExpressionFromLiteral( Token::Value token, int pos, @@ -690,65 +742,67 @@ Expression* ParserTraits::ParseV8Intrinsic(bool* ok) { FunctionLiteral* ParserTraits::ParseFunctionLiteral( - const AstRawString* name, - Scanner::Location function_name_location, - bool name_is_strict_reserved, - bool is_generator, - int function_token_position, - FunctionLiteral::FunctionType type, - FunctionLiteral::ArityRestriction arity_restriction, - bool* ok) { - return parser_->ParseFunctionLiteral(name, function_name_location, - name_is_strict_reserved, is_generator, - function_token_position, type, - arity_restriction, ok); + const AstRawString* name, Scanner::Location function_name_location, + bool name_is_strict_reserved, FunctionKind kind, + int function_token_position, FunctionLiteral::FunctionType type, + FunctionLiteral::ArityRestriction arity_restriction, bool* ok) { + return parser_->ParseFunctionLiteral( + name, function_name_location, name_is_strict_reserved, kind, + function_token_position, type, arity_restriction, ok); } -Parser::Parser(CompilationInfo* info) - : ParserBase<ParserTraits>(&scanner_, - info->isolate()->stack_guard()->real_climit(), - info->extension(), NULL, info->zone(), this), - isolate_(info->isolate()), - script_(info->script()), - scanner_(isolate_->unicode_cache()), +Parser::Parser(CompilationInfo* info, ParseInfo* parse_info) + : ParserBase<ParserTraits>(&scanner_, parse_info->stack_limit, + info->extension(), NULL, info->zone(), + info->ast_node_id_gen(), this), + scanner_(parse_info->unicode_cache), reusable_preparser_(NULL), original_scope_(NULL), target_stack_(NULL), cached_parse_data_(NULL), - ast_value_factory_(NULL), info_(info), has_pending_error_(false), pending_error_message_(NULL), pending_error_arg_(NULL), - pending_error_char_arg_(NULL) { - DCHECK(!script_.is_null()); - isolate_->set_ast_node_id(0); + pending_error_char_arg_(NULL), + total_preparse_skipped_(0), + pre_parse_timer_(NULL) { + DCHECK(!script().is_null() || info->source_stream() != NULL); set_allow_harmony_scoping(!info->is_native() && FLAG_harmony_scoping); set_allow_modules(!info->is_native() && FLAG_harmony_modules); set_allow_natives_syntax(FLAG_allow_natives_syntax || info->is_native()); set_allow_lazy(false); // Must be explicitly enabled. - set_allow_generators(FLAG_harmony_generators); set_allow_arrow_functions(FLAG_harmony_arrow_functions); set_allow_harmony_numeric_literals(FLAG_harmony_numeric_literals); + set_allow_classes(FLAG_harmony_classes); + set_allow_harmony_object_literals(FLAG_harmony_object_literals); for (int feature = 0; feature < v8::Isolate::kUseCounterFeatureCount; ++feature) { use_counts_[feature] = 0; } + if (info->ast_value_factory() == NULL) { + // info takes ownership of AstValueFactory. + info->SetAstValueFactory( + new AstValueFactory(zone(), parse_info->hash_seed)); + } } FunctionLiteral* Parser::ParseProgram() { // TODO(bmeurer): We temporarily need to pass allow_nesting = true here, // see comment for HistogramTimerScope class. + + // It's OK to use the counters here, since this function is only called in + // the main thread. HistogramTimerScope timer_scope(isolate()->counters()->parse(), true); - Handle<String> source(String::cast(script_->source())); + Handle<String> source(String::cast(script()->source())); isolate()->counters()->total_parse_size()->Increment(source->length()); base::ElapsedTimer timer; if (FLAG_trace_parse) { timer.Start(); } - fni_ = new(zone()) FuncNameInferrer(ast_value_factory_, zone()); + fni_ = new (zone()) FuncNameInferrer(ast_value_factory(), zone()); // Initialize parser state. CompleteParserRecorder recorder; @@ -761,6 +815,9 @@ FunctionLiteral* Parser::ParseProgram() { source = String::Flatten(source); FunctionLiteral* result; + + Scope* top_scope = NULL; + Scope* eval_scope = NULL; 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 @@ -768,12 +825,17 @@ FunctionLiteral* Parser::ParseProgram() { ExternalTwoByteStringUtf16CharacterStream stream( Handle<ExternalTwoByteString>::cast(source), 0, source->length()); scanner_.Initialize(&stream); - result = DoParseProgram(info(), source); + result = DoParseProgram(info(), &top_scope, &eval_scope); } else { GenericStringUtf16CharacterStream stream(source, 0, source->length()); scanner_.Initialize(&stream); - result = DoParseProgram(info(), source); + result = DoParseProgram(info(), &top_scope, &eval_scope); } + top_scope->set_end_position(source->length()); + if (eval_scope != NULL) { + eval_scope->set_end_position(source->length()); + } + HandleSourceURLComments(); if (FLAG_trace_parse && result != NULL) { double ms = timer.Elapsed().InMillisecondsF(); @@ -796,53 +858,52 @@ FunctionLiteral* Parser::ParseProgram() { } -FunctionLiteral* Parser::DoParseProgram(CompilationInfo* info, - Handle<String> source) { +FunctionLiteral* Parser::DoParseProgram(CompilationInfo* info, Scope** scope, + Scope** eval_scope) { DCHECK(scope_ == NULL); DCHECK(target_stack_ == NULL); FunctionLiteral* result = NULL; - { Scope* scope = NewScope(scope_, GLOBAL_SCOPE); - info->SetGlobalScope(scope); + { + *scope = NewScope(scope_, GLOBAL_SCOPE); + info->SetGlobalScope(*scope); if (!info->context().is_null() && !info->context()->IsNativeContext()) { - scope = Scope::DeserializeScopeChain(*info->context(), scope, zone()); + *scope = Scope::DeserializeScopeChain(*info->context(), *scope, zone()); // The Scope is backed up by ScopeInfo (which is in the V8 heap); this // means the Parser cannot operate independent of the V8 heap. Tell the // string table to internalize strings and values right after they're // created. - ast_value_factory_->Internalize(isolate()); + ast_value_factory()->Internalize(isolate()); } - original_scope_ = scope; + original_scope_ = *scope; if (info->is_eval()) { - if (!scope->is_global_scope() || info->strict_mode() == STRICT) { - scope = NewScope(scope, EVAL_SCOPE); + if (!(*scope)->is_global_scope() || info->strict_mode() == STRICT) { + *scope = NewScope(*scope, EVAL_SCOPE); } } else if (info->is_global()) { - scope = NewScope(scope, GLOBAL_SCOPE); + *scope = NewScope(*scope, GLOBAL_SCOPE); } - scope->set_start_position(0); - scope->set_end_position(source->length()); + (*scope)->set_start_position(0); + // End position will be set by the caller. // Compute the parsing mode. Mode mode = (FLAG_lazy && allow_lazy()) ? PARSE_LAZILY : PARSE_EAGERLY; - if (allow_natives_syntax() || - extension_ != NULL || - scope->is_eval_scope()) { + if (allow_natives_syntax() || extension_ != NULL || + (*scope)->is_eval_scope()) { mode = PARSE_EAGERLY; } ParsingModeScope parsing_mode(this, mode); // Enters 'scope'. - FunctionState function_state(&function_state_, &scope_, scope, zone(), - ast_value_factory_); + FunctionState function_state(&function_state_, &scope_, *scope, zone(), + ast_value_factory(), info->ast_node_id_gen()); scope_->SetStrictMode(info->strict_mode()); ZoneList<Statement*>* body = new(zone()) ZoneList<Statement*>(16, zone()); bool ok = true; int beg_pos = scanner()->location().beg_pos; - ParseSourceElements(body, Token::EOS, info->is_eval(), true, &ok); - - HandleSourceURLComments(); + ParseSourceElements(body, Token::EOS, info->is_eval(), true, eval_scope, + &ok); if (ok && strict_mode() == STRICT) { CheckOctalLiteral(beg_pos, scanner()->location().end_pos, &ok); @@ -862,24 +923,18 @@ FunctionLiteral* Parser::DoParseProgram(CompilationInfo* info, } } - ast_value_factory_->Internalize(isolate()); if (ok) { result = factory()->NewFunctionLiteral( - ast_value_factory_->empty_string(), ast_value_factory_, scope_, body, - function_state.materialized_literal_count(), + ast_value_factory()->empty_string(), ast_value_factory(), scope_, + body, function_state.materialized_literal_count(), function_state.expected_property_count(), function_state.handler_count(), 0, FunctionLiteral::kNoDuplicateParameters, FunctionLiteral::ANONYMOUS_EXPRESSION, FunctionLiteral::kGlobalOrEval, - FunctionLiteral::kNotParenthesized, FunctionLiteral::kNormalFunction, - 0); + FunctionLiteral::kNotParenthesized, FunctionKind::kNormalFunction, 0); result->set_ast_properties(factory()->visitor()->ast_properties()); result->set_dont_optimize_reason( factory()->visitor()->dont_optimize_reason()); - } else if (stack_overflow()) { - isolate()->StackOverflow(); - } else { - ThrowPendingError(); } } @@ -891,8 +946,10 @@ FunctionLiteral* Parser::DoParseProgram(CompilationInfo* info, FunctionLiteral* Parser::ParseLazy() { + // It's OK to use the counters here, since this function is only called in + // the main thread. HistogramTimerScope timer_scope(isolate()->counters()->parse_lazy()); - Handle<String> source(String::cast(script_->source())); + Handle<String> source(String::cast(script()->source())); isolate()->counters()->total_parse_size()->Increment(source->length()); base::ElapsedTimer timer; if (FLAG_trace_parse) { @@ -932,9 +989,9 @@ FunctionLiteral* Parser::ParseLazy(Utf16CharacterStream* source) { DCHECK(target_stack_ == NULL); Handle<String> name(String::cast(shared_info->name())); - DCHECK(ast_value_factory_); - fni_ = new(zone()) FuncNameInferrer(ast_value_factory_, zone()); - const AstRawString* raw_name = ast_value_factory_->GetString(name); + DCHECK(ast_value_factory()); + fni_ = new (zone()) FuncNameInferrer(ast_value_factory(), zone()); + const AstRawString* raw_name = ast_value_factory()->GetString(name); fni_->PushEnclosingName(raw_name); ParsingModeScope parsing_mode(this, PARSE_EAGERLY); @@ -952,7 +1009,8 @@ FunctionLiteral* Parser::ParseLazy(Utf16CharacterStream* source) { } original_scope_ = scope; FunctionState function_state(&function_state_, &scope_, scope, zone(), - ast_value_factory_); + ast_value_factory(), + info()->ast_node_id_gen()); DCHECK(scope->strict_mode() == SLOPPY || info()->strict_mode() == STRICT); DCHECK(info()->strict_mode() == shared_info->strict_mode()); scope->SetStrictMode(shared_info->strict_mode()); @@ -961,18 +1019,16 @@ FunctionLiteral* Parser::ParseLazy(Utf16CharacterStream* source) { ? FunctionLiteral::ANONYMOUS_EXPRESSION : FunctionLiteral::NAMED_EXPRESSION) : FunctionLiteral::DECLARATION; - bool is_generator = shared_info->is_generator(); bool ok = true; if (shared_info->is_arrow()) { - DCHECK(!is_generator); Expression* expression = ParseExpression(false, &ok); DCHECK(expression->IsFunctionLiteral()); result = expression->AsFunctionLiteral(); } else { result = ParseFunctionLiteral(raw_name, Scanner::Location::invalid(), false, // Strict mode name already checked. - is_generator, RelocInfo::kNoPosition, + shared_info->kind(), RelocInfo::kNoPosition, function_type, FunctionLiteral::NORMAL_ARITY, &ok); } @@ -983,14 +1039,7 @@ FunctionLiteral* Parser::ParseLazy(Utf16CharacterStream* source) { // Make sure the target stack is empty. DCHECK(target_stack_ == NULL); - ast_value_factory_->Internalize(isolate()); - if (result == NULL) { - if (stack_overflow()) { - isolate()->StackOverflow(); - } else { - ThrowPendingError(); - } - } else { + if (result != NULL) { Handle<String> inferred_name(shared_info->inferred_name()); result->set_inferred_name(inferred_name); } @@ -999,10 +1048,8 @@ FunctionLiteral* Parser::ParseLazy(Utf16CharacterStream* source) { void* Parser::ParseSourceElements(ZoneList<Statement*>* processor, - int end_token, - bool is_eval, - bool is_global, - bool* ok) { + int end_token, bool is_eval, bool is_global, + Scope** eval_scope, bool* ok) { // SourceElements :: // (ModuleElement)* <end_token> @@ -1044,9 +1091,9 @@ void* Parser::ParseSourceElements(ZoneList<Statement*>* processor, // one can be present. if (strict_mode() == SLOPPY && literal->raw_value()->AsString() == - ast_value_factory_->use_strict_string() && + ast_value_factory()->use_strict_string() && token_loc.end_pos - token_loc.beg_pos == - ast_value_factory_->use_strict_string()->length() + 2) { + ast_value_factory()->use_strict_string()->length() + 2) { // TODO(mstarzinger): Global strict eval calls, need their own scope // as specified in ES5 10.4.2(3). The correct fix would be to always // add this scope in DoParseProgram(), but that requires adaptations @@ -1058,18 +1105,23 @@ void* Parser::ParseSourceElements(ZoneList<Statement*>* processor, scope->set_start_position(scope_->start_position()); scope->set_end_position(scope_->end_position()); scope_ = scope; + if (eval_scope != NULL) { + // Caller will correct the positions of the ad hoc eval scope. + *eval_scope = scope; + } mode_ = PARSE_EAGERLY; } scope_->SetStrictMode(STRICT); // "use strict" is the only directive for now. directive_prologue = false; } else if (literal->raw_value()->AsString() == - ast_value_factory_->use_asm_string() && + ast_value_factory()->use_asm_string() && token_loc.end_pos - token_loc.beg_pos == - ast_value_factory_->use_asm_string()->length() + 2) { + ast_value_factory()->use_asm_string()->length() + 2) { // Store the usage count; The actual use counter on the isolate is // incremented after parsing is done. ++use_counts_[v8::Isolate::kUseAsm]; + scope_->SetAsmModule(); } } else { // End of the directive prologue. @@ -1103,6 +1155,8 @@ Statement* Parser::ParseModuleElement(ZoneList<const AstRawString*>* labels, switch (peek()) { case Token::FUNCTION: return ParseFunctionDeclaration(NULL, ok); + case Token::CLASS: + return ParseClassDeclaration(NULL, ok); case Token::IMPORT: return ParseImportDeclaration(ok); case Token::EXPORT: @@ -1125,7 +1179,7 @@ Statement* Parser::ParseModuleElement(ZoneList<const AstRawString*>* labels, ExpressionStatement* estmt = stmt->AsExpressionStatement(); if (estmt != NULL && estmt->expression()->AsVariableProxy() != NULL && estmt->expression()->AsVariableProxy()->raw_name() == - ast_value_factory_->module_string() && + ast_value_factory()->module_string() && !scanner()->literal_contains_escapes()) { return ParseModuleDeclaration(NULL, ok); } @@ -1423,7 +1477,7 @@ Statement* Parser::ParseExportDeclaration(bool* ok) { const AstRawString* name = ParseIdentifier(kDontAllowEvalOrArguments, CHECK_OK); // Handle 'module' as a context-sensitive keyword. - if (name != ast_value_factory_->module_string()) { + if (name != ast_value_factory()->module_string()) { names.Add(name, zone()); while (peek() == Token::COMMA) { Consume(Token::COMMA); @@ -1442,6 +1496,10 @@ Statement* Parser::ParseExportDeclaration(bool* ok) { result = ParseFunctionDeclaration(&names, CHECK_OK); break; + case Token::CLASS: + result = ParseClassDeclaration(&names, CHECK_OK); + break; + case Token::VAR: case Token::LET: case Token::CONST: @@ -1504,10 +1562,13 @@ Statement* Parser::ParseBlockElement(ZoneList<const AstRawString*>* labels, // LetDeclaration // ConstDeclaration // GeneratorDeclaration + // ClassDeclaration switch (peek()) { case Token::FUNCTION: return ParseFunctionDeclaration(NULL, ok); + case Token::CLASS: + return ParseClassDeclaration(NULL, ok); case Token::CONST: return ParseVariableStatement(kModuleElement, NULL, ok); case Token::LET: @@ -1619,6 +1680,9 @@ Statement* Parser::ParseStatement(ZoneList<const AstRawString*>* labels, return ParseFunctionDeclaration(NULL, ok); } + case Token::CLASS: + return ParseClassDeclaration(NULL, ok); + case Token::DEBUGGER: return ParseDebuggerStatement(ok); @@ -1859,18 +1923,16 @@ Statement* Parser::ParseFunctionDeclaration( // '{' FunctionBody '}' Expect(Token::FUNCTION, CHECK_OK); int pos = position(); - bool is_generator = allow_generators() && Check(Token::MUL); + bool is_generator = Check(Token::MUL); bool is_strict_reserved = false; const AstRawString* name = ParseIdentifierOrStrictReservedWord( &is_strict_reserved, CHECK_OK); - FunctionLiteral* fun = ParseFunctionLiteral(name, - scanner()->location(), - is_strict_reserved, - is_generator, - pos, - FunctionLiteral::DECLARATION, - FunctionLiteral::NORMAL_ARITY, - CHECK_OK); + FunctionLiteral* fun = + ParseFunctionLiteral(name, scanner()->location(), is_strict_reserved, + is_generator ? FunctionKind::kGeneratorFunction + : FunctionKind::kNormalFunction, + pos, FunctionLiteral::DECLARATION, + FunctionLiteral::NORMAL_ARITY, CHECK_OK); // Even if we're not at the top-level of the global or a function // scope, we treat it as such and introduce the function with its // initial value upon entering the corresponding scope. @@ -1889,6 +1951,47 @@ Statement* Parser::ParseFunctionDeclaration( } +Statement* Parser::ParseClassDeclaration(ZoneList<const AstRawString*>* names, + bool* ok) { + // ClassDeclaration :: + // 'class' Identifier ('extends' LeftHandExpression)? '{' ClassBody '}' + // + // A ClassDeclaration + // + // class C { ... } + // + // has the same semantics as: + // + // let C = class C { ... }; + // + // so rewrite it as such. + + Expect(Token::CLASS, CHECK_OK); + int pos = position(); + bool is_strict_reserved = false; + const AstRawString* name = + ParseIdentifierOrStrictReservedWord(&is_strict_reserved, CHECK_OK); + Expression* value = ParseClassLiteral(name, scanner()->location(), + is_strict_reserved, pos, CHECK_OK); + + Block* block = factory()->NewBlock(NULL, 1, true, pos); + VariableMode mode = LET; + VariableProxy* proxy = NewUnresolved(name, mode, Interface::NewValue()); + Declaration* declaration = + factory()->NewVariableDeclaration(proxy, mode, scope_, pos); + Declare(declaration, true, CHECK_OK); + + Token::Value init_op = Token::INIT_LET; + Assignment* assignment = factory()->NewAssignment(init_op, proxy, value, pos); + block->AddStatement( + factory()->NewExpressionStatement(assignment, RelocInfo::kNoPosition), + zone()); + + if (names) names->Add(name, zone()); + return block; +} + + Block* Parser::ParseBlock(ZoneList<const AstRawString*>* labels, bool* ok) { if (allow_harmony_scoping() && strict_mode() == STRICT) { return ParseScopedBlock(labels, ok); @@ -2200,9 +2303,9 @@ Block* Parser::ParseVariableDeclarations( // Note that the function does different things depending on // the number of arguments (1 or 2). initialize = factory()->NewCallRuntime( - ast_value_factory_->initialize_const_global_string(), - Runtime::FunctionForId(Runtime::kInitializeConstGlobal), - arguments, pos); + ast_value_factory()->initialize_const_global_string(), + Runtime::FunctionForId(Runtime::kInitializeConstGlobal), arguments, + pos); } else { // Add strict mode. // We may want to pass singleton to avoid Literal allocations. @@ -2219,7 +2322,7 @@ Block* Parser::ParseVariableDeclarations( // Construct the call to Runtime_InitializeVarGlobal // and add it to the initialization statement block. initialize = factory()->NewCallRuntime( - ast_value_factory_->initialize_var_global_string(), + ast_value_factory()->initialize_var_global_string(), Runtime::FunctionForId(Runtime::kInitializeVarGlobal), arguments, pos); } else { @@ -2334,25 +2437,22 @@ Statement* Parser::ParseExpressionOrLabelledStatement( // If we have an extension, we allow a native function declaration. // A native function declaration starts with "native function" with // no line-terminator between the two words. - if (extension_ != NULL && - peek() == Token::FUNCTION && - !scanner()->HasAnyLineTerminatorBeforeNext() && - expr != NULL && + if (extension_ != NULL && peek() == Token::FUNCTION && + !scanner()->HasAnyLineTerminatorBeforeNext() && expr != NULL && expr->AsVariableProxy() != NULL && expr->AsVariableProxy()->raw_name() == - ast_value_factory_->native_string() && + ast_value_factory()->native_string() && !scanner()->literal_contains_escapes()) { return ParseNativeDeclaration(ok); } // Parsed expression statement, or the context-sensitive 'module' keyword. // Only expect semicolon in the former case. - if (!FLAG_harmony_modules || - peek() != Token::IDENTIFIER || + if (!FLAG_harmony_modules || peek() != Token::IDENTIFIER || scanner()->HasAnyLineTerminatorBeforeNext() || expr->AsVariableProxy() == NULL || expr->AsVariableProxy()->raw_name() != - ast_value_factory_->module_string() || + ast_value_factory()->module_string() || scanner()->literal_contains_escapes()) { ExpectSemicolon(CHECK_OK); } @@ -2475,7 +2575,7 @@ Statement* Parser::ParseReturnStatement(bool* ok) { Expression* generator = factory()->NewVariableProxy( function_state_->generator_object_variable()); Expression* yield = factory()->NewYield( - generator, return_value, Yield::FINAL, loc.beg_pos); + generator, return_value, Yield::kFinal, loc.beg_pos); result = factory()->NewExpressionStatement(yield, loc.beg_pos); } else { result = factory()->NewReturnStatement(return_value, loc.beg_pos); @@ -2774,9 +2874,9 @@ void Parser::InitializeForEachStatement(ForEachStatement* stmt, if (for_of != NULL) { Variable* iterator = scope_->DeclarationScope()->NewTemporary( - ast_value_factory_->dot_iterator_string()); + ast_value_factory()->dot_iterator_string()); Variable* result = scope_->DeclarationScope()->NewTemporary( - ast_value_factory_->dot_result_string()); + ast_value_factory()->dot_result_string()); Expression* assign_iterator; Expression* next_result; @@ -2792,7 +2892,7 @@ void Parser::InitializeForEachStatement(ForEachStatement* stmt, { Expression* iterator_proxy = factory()->NewVariableProxy(iterator); Expression* next_literal = factory()->NewStringLiteral( - ast_value_factory_->next_string(), RelocInfo::kNoPosition); + ast_value_factory()->next_string(), RelocInfo::kNoPosition); Expression* next_property = factory()->NewProperty( iterator_proxy, next_literal, RelocInfo::kNoPosition); ZoneList<Expression*>* next_arguments = @@ -2807,7 +2907,7 @@ void Parser::InitializeForEachStatement(ForEachStatement* stmt, // result.done { Expression* done_literal = factory()->NewStringLiteral( - ast_value_factory_->done_string(), RelocInfo::kNoPosition); + ast_value_factory()->done_string(), RelocInfo::kNoPosition); Expression* result_proxy = factory()->NewVariableProxy(result); result_done = factory()->NewProperty( result_proxy, done_literal, RelocInfo::kNoPosition); @@ -2816,7 +2916,7 @@ void Parser::InitializeForEachStatement(ForEachStatement* stmt, // each = result.value { Expression* value_literal = factory()->NewStringLiteral( - ast_value_factory_->value_string(), RelocInfo::kNoPosition); + ast_value_factory()->value_string(), RelocInfo::kNoPosition); Expression* result_proxy = factory()->NewVariableProxy(result); Expression* result_value = factory()->NewProperty( result_proxy, value_literal, RelocInfo::kNoPosition); @@ -2879,7 +2979,7 @@ Statement* Parser::DesugarLetBindingsInForStatement( RelocInfo::kNoPosition); outer_block->AddStatement(init, zone()); - const AstRawString* temp_name = ast_value_factory_->dot_for_string(); + const AstRawString* temp_name = ast_value_factory()->dot_for_string(); // For each let variable x: // make statement: temp_x = x. @@ -3077,7 +3177,7 @@ Statement* Parser::ParseForStatement(ZoneList<const AstRawString*>* labels, // TODO(keuchel): Move the temporary variable to the block scope, after // implementing stack allocated block scoped variables. Variable* temp = scope_->DeclarationScope()->NewTemporary( - ast_value_factory_->dot_for_string()); + ast_value_factory()->dot_for_string()); VariableProxy* temp_proxy = factory()->NewVariableProxy(temp); ForEachStatement* loop = factory()->NewForEachStatement(mode, labels, pos); @@ -3334,14 +3434,10 @@ int ParserTraits::DeclareArrowParametersFromExpression( FunctionLiteral* Parser::ParseFunctionLiteral( - const AstRawString* function_name, - Scanner::Location function_name_location, - bool name_is_strict_reserved, - bool is_generator, - int function_token_pos, + const AstRawString* function_name, Scanner::Location function_name_location, + bool name_is_strict_reserved, FunctionKind kind, int function_token_pos, FunctionLiteral::FunctionType function_type, - FunctionLiteral::ArityRestriction arity_restriction, - bool* ok) { + FunctionLiteral::ArityRestriction arity_restriction, bool* ok) { // Function :: // '(' FormalParameterList? ')' '{' FunctionBody '}' // @@ -3354,6 +3450,8 @@ FunctionLiteral* Parser::ParseFunctionLiteral( int pos = function_token_pos == RelocInfo::kNoPosition ? peek_position() : function_token_pos; + bool is_generator = IsGeneratorFunction(kind); + // Anonymous functions were passed either the empty symbol or a null // handle as the function name. Remember if we were passed a non-empty // handle to decide whether to invoke function name inference. @@ -3361,7 +3459,7 @@ FunctionLiteral* Parser::ParseFunctionLiteral( // We want a non-null handle as the function name. if (should_infer_name) { - function_name = ast_value_factory_->empty_string(); + function_name = ast_value_factory()->empty_string(); } int num_parameters = 0; @@ -3415,7 +3513,8 @@ FunctionLiteral* Parser::ParseFunctionLiteral( // Parse function body. { FunctionState function_state(&function_state_, &scope_, scope, zone(), - ast_value_factory_); + ast_value_factory(), + info()->ast_node_id_gen()); scope_->SetScopeName(function_name); if (is_generator) { @@ -3428,7 +3527,7 @@ FunctionLiteral* Parser::ParseFunctionLiteral( // in a temporary variable, a definition that is used by "yield" // expressions. This also marks the FunctionState as a generator. Variable* temp = scope_->DeclarationScope()->NewTemporary( - ast_value_factory_->dot_generator_object_string()); + ast_value_factory()->dot_generator_object_string()); function_state.set_generator_object_variable(temp); } @@ -3562,7 +3661,8 @@ FunctionLiteral* Parser::ParseFunctionLiteral( } // Validate strict mode. - if (strict_mode() == STRICT) { + // Concise methods use StrictFormalParameters. + if (strict_mode() == STRICT || IsConciseMethod(kind)) { CheckStrictFunctionNameAndParameters(function_name, name_is_strict_reserved, function_name_location, @@ -3570,6 +3670,8 @@ FunctionLiteral* Parser::ParseFunctionLiteral( dupe_error_loc, reserved_loc, CHECK_OK); + } + if (strict_mode() == STRICT) { CheckOctalLiteral(scope->start_position(), scope->end_position(), CHECK_OK); @@ -3582,11 +3684,8 @@ FunctionLiteral* Parser::ParseFunctionLiteral( } } - FunctionLiteral::KindFlag kind = is_generator - ? FunctionLiteral::kGeneratorFunction - : FunctionLiteral::kNormalFunction; FunctionLiteral* function_literal = factory()->NewFunctionLiteral( - function_name, ast_value_factory_, scope, body, + function_name, ast_value_factory(), scope, body, materialized_literal_count, expected_property_count, handler_count, num_parameters, duplicate_parameters, function_type, FunctionLiteral::kIsFunction, parenthesized, kind, pos); @@ -3620,8 +3719,7 @@ void Parser::SkipLazyFunctionBody(const AstRawString* function_name, if (!*ok) { return; } - isolate()->counters()->total_preparse_skipped()->Increment( - scope_->end_position() - function_block_pos); + total_preparse_skipped_ += scope_->end_position() - function_block_pos; *materialized_literal_count = entry.literal_count(); *expected_property_count = entry.property_count(); scope_->SetStrictMode(entry.strict_mode()); @@ -3649,8 +3747,7 @@ void Parser::SkipLazyFunctionBody(const AstRawString* function_name, if (!*ok) { return; } - isolate()->counters()->total_preparse_skipped()->Increment( - scope_->end_position() - function_block_pos); + total_preparse_skipped_ += scope_->end_position() - function_block_pos; *materialized_literal_count = logger.literals(); *expected_property_count = logger.properties(); scope_->SetStrictMode(logger.strict_mode()); @@ -3691,9 +3788,9 @@ ZoneList<Statement*>* Parser::ParseEagerFunctionBody( ZoneList<Expression*>* arguments = new(zone()) ZoneList<Expression*>(0, zone()); CallRuntime* allocation = factory()->NewCallRuntime( - ast_value_factory_->empty_string(), - Runtime::FunctionForId(Runtime::kCreateJSGeneratorObject), - arguments, pos); + ast_value_factory()->empty_string(), + Runtime::FunctionForId(Runtime::kCreateJSGeneratorObject), arguments, + pos); VariableProxy* init_proxy = factory()->NewVariableProxy( function_state_->generator_object_variable()); Assignment* assignment = factory()->NewAssignment( @@ -3701,19 +3798,19 @@ ZoneList<Statement*>* Parser::ParseEagerFunctionBody( VariableProxy* get_proxy = factory()->NewVariableProxy( function_state_->generator_object_variable()); Yield* yield = factory()->NewYield( - get_proxy, assignment, Yield::INITIAL, RelocInfo::kNoPosition); + get_proxy, assignment, Yield::kInitial, RelocInfo::kNoPosition); body->Add(factory()->NewExpressionStatement( yield, RelocInfo::kNoPosition), zone()); } - ParseSourceElements(body, Token::RBRACE, false, false, CHECK_OK); + ParseSourceElements(body, Token::RBRACE, false, false, NULL, CHECK_OK); if (is_generator) { VariableProxy* get_proxy = factory()->NewVariableProxy( function_state_->generator_object_variable()); Expression* undefined = factory()->NewUndefinedLiteral(RelocInfo::kNoPosition); - Yield* yield = factory()->NewYield(get_proxy, undefined, Yield::FINAL, + Yield* yield = factory()->NewYield(get_proxy, undefined, Yield::kFinal, RelocInfo::kNoPosition); body->Add(factory()->NewExpressionStatement( yield, RelocInfo::kNoPosition), zone()); @@ -3728,25 +3825,33 @@ ZoneList<Statement*>* Parser::ParseEagerFunctionBody( PreParser::PreParseResult Parser::ParseLazyFunctionBodyWithPreParser( SingletonLogger* logger) { - HistogramTimerScope preparse_scope(isolate()->counters()->pre_parse()); + // This function may be called on a background thread too; record only the + // main thread preparse times. + if (pre_parse_timer_ != NULL) { + pre_parse_timer_->Start(); + } DCHECK_EQ(Token::LBRACE, scanner()->current_token()); if (reusable_preparser_ == NULL) { - intptr_t stack_limit = isolate()->stack_guard()->real_climit(); - reusable_preparser_ = new PreParser(&scanner_, NULL, stack_limit); + reusable_preparser_ = new PreParser(&scanner_, NULL, stack_limit_); reusable_preparser_->set_allow_harmony_scoping(allow_harmony_scoping()); reusable_preparser_->set_allow_modules(allow_modules()); reusable_preparser_->set_allow_natives_syntax(allow_natives_syntax()); reusable_preparser_->set_allow_lazy(true); - reusable_preparser_->set_allow_generators(allow_generators()); reusable_preparser_->set_allow_arrow_functions(allow_arrow_functions()); reusable_preparser_->set_allow_harmony_numeric_literals( allow_harmony_numeric_literals()); + reusable_preparser_->set_allow_classes(allow_classes()); + reusable_preparser_->set_allow_harmony_object_literals( + allow_harmony_object_literals()); } PreParser::PreParseResult result = reusable_preparser_->PreParseLazyFunction(strict_mode(), is_generator(), logger); + if (pre_parse_timer_ != NULL) { + pre_parse_timer_->Stop(); + } return result; } @@ -3899,10 +4004,9 @@ void Parser::HandleSourceURLComments() { void Parser::ThrowPendingError() { - DCHECK(ast_value_factory_->IsInternalized()); + DCHECK(ast_value_factory()->IsInternalized()); if (has_pending_error_) { - MessageLocation location(script_, - pending_error_location_.beg_pos, + MessageLocation location(script(), pending_error_location_.beg_pos, pending_error_location_.end_pos); Factory* factory = isolate()->factory(); bool has_arg = @@ -3917,24 +4021,41 @@ void Parser::ThrowPendingError() { .ToHandleChecked(); elements->set(0, *arg_string); } - isolate()->debug()->OnCompileError(script_); + isolate()->debug()->OnCompileError(script()); Handle<JSArray> array = factory->NewJSArrayWithElements(elements); - Handle<Object> result = pending_error_is_reference_error_ - ? factory->NewReferenceError(pending_error_message_, array) - : factory->NewSyntaxError(pending_error_message_, array); - isolate()->Throw(*result, &location); + Handle<Object> error; + MaybeHandle<Object> maybe_error = + pending_error_is_reference_error_ + ? factory->NewReferenceError(pending_error_message_, array) + : factory->NewSyntaxError(pending_error_message_, array); + if (maybe_error.ToHandle(&error)) isolate()->Throw(*error, &location); } } -void Parser::InternalizeUseCounts() { +void Parser::Internalize() { + // Internalize strings. + ast_value_factory()->Internalize(isolate()); + + // Error processing. + if (info()->function() == NULL) { + if (stack_overflow()) { + isolate()->StackOverflow(); + } else { + ThrowPendingError(); + } + } + + // Move statistics to Isolate. for (int feature = 0; feature < v8::Isolate::kUseCounterFeatureCount; ++feature) { for (int i = 0; i < use_counts_[feature]; ++i) { isolate()->CountUsage(v8::Isolate::UseCounterFeature(feature)); } } + isolate()->counters()->total_preparse_skipped()->Increment( + total_preparse_skipped_); } @@ -4772,16 +4893,12 @@ bool RegExpParser::ParseRegExp(FlatStringReader* input, bool Parser::Parse() { DCHECK(info()->function() == NULL); FunctionLiteral* result = NULL; - ast_value_factory_ = info()->ast_value_factory(); - if (ast_value_factory_ == NULL) { - ast_value_factory_ = - new AstValueFactory(zone(), isolate()->heap()->HashSeed()); - } - if (allow_natives_syntax() || extension_ != NULL) { + pre_parse_timer_ = isolate()->counters()->pre_parse(); + if (FLAG_trace_parse || allow_natives_syntax() || extension_ != NULL) { // If intrinsics are allowed, the Parser cannot operate independent of the - // V8 heap because of Rumtime. Tell the string table to internalize strings + // V8 heap because of Runtime. Tell the string table to internalize strings // and values right after they're created. - ast_value_factory_->Internalize(isolate()); + ast_value_factory()->Internalize(isolate()); } if (info()->is_lazy()) { @@ -4796,16 +4913,52 @@ bool Parser::Parse() { result = ParseProgram(); } info()->SetFunction(result); - DCHECK(ast_value_factory_->IsInternalized()); - // info takes ownership of ast_value_factory_. - if (info()->ast_value_factory() == NULL) { - info()->SetAstValueFactory(ast_value_factory_); - } - ast_value_factory_ = NULL; - - InternalizeUseCounts(); + Internalize(); + DCHECK(ast_value_factory()->IsInternalized()); return (result != NULL); } + +void Parser::ParseOnBackground() { + DCHECK(info()->function() == NULL); + FunctionLiteral* result = NULL; + fni_ = new (zone()) FuncNameInferrer(ast_value_factory(), zone()); + + CompleteParserRecorder recorder; + if (compile_options() == ScriptCompiler::kProduceParserCache) { + log_ = &recorder; + } + + DCHECK(info()->source_stream() != NULL); + ExternalStreamingStream stream(info()->source_stream(), + info()->source_stream_encoding()); + scanner_.Initialize(&stream); + DCHECK(info()->context().is_null() || info()->context()->IsNativeContext()); + + // When streaming, we don't know the length of the source until we have parsed + // it. The raw data can be UTF-8, so we wouldn't know the source length until + // we have decoded it anyway even if we knew the raw data length (which we + // don't). We work around this by storing all the scopes which need their end + // position set at the end of the script (the top scope and possible eval + // scopes) and set their end position after we know the script length. + Scope* top_scope = NULL; + Scope* eval_scope = NULL; + result = DoParseProgram(info(), &top_scope, &eval_scope); + + top_scope->set_end_position(scanner()->location().end_pos); + if (eval_scope != NULL) { + eval_scope->set_end_position(scanner()->location().end_pos); + } + + info()->SetFunction(result); + + // We cannot internalize on a background thread; a foreground task will take + // care of calling Parser::Internalize just before compilation. + + if (compile_options() == ScriptCompiler::kProduceParserCache) { + if (result != NULL) *info_->cached_data() = recorder.GetScriptData(); + log_ = NULL; + } +} } } // namespace v8::internal |