LCOV - code coverage report
Current view: top level - src/parsing - preparser.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 115 117 98.3 %
Date: 2017-10-20 Functions: 9 9 100.0 %

          Line data    Source code
       1             : // Copyright 2011 the V8 project authors. All rights reserved.
       2             : // Use of this source code is governed by a BSD-style license that can be
       3             : // found in the LICENSE file.
       4             : 
       5             : #include <cmath>
       6             : 
       7             : #include "src/allocation.h"
       8             : #include "src/base/logging.h"
       9             : #include "src/conversions-inl.h"
      10             : #include "src/conversions.h"
      11             : #include "src/globals.h"
      12             : #include "src/parsing/duplicate-finder.h"
      13             : #include "src/parsing/parser-base.h"
      14             : #include "src/parsing/preparse-data-format.h"
      15             : #include "src/parsing/preparse-data.h"
      16             : #include "src/parsing/preparsed-scope-data.h"
      17             : #include "src/parsing/preparser.h"
      18             : #include "src/unicode.h"
      19             : #include "src/utils.h"
      20             : 
      21             : namespace v8 {
      22             : namespace internal {
      23             : 
      24             : // ----------------------------------------------------------------------------
      25             : // The CHECK_OK macro is a convenient macro to enforce error
      26             : // handling for functions that may fail (by returning !*ok).
      27             : //
      28             : // CAUTION: This macro appends extra statements after a call,
      29             : // thus it must never be used where only a single statement
      30             : // is correct (e.g. an if statement branch w/o braces)!
      31             : 
      32             : #define CHECK_OK_VALUE(x) ok); \
      33             :   if (!*ok) return x;          \
      34             :   ((void)0
      35             : #define DUMMY )  // to make indentation work
      36             : #undef DUMMY
      37             : 
      38             : #define CHECK_OK CHECK_OK_VALUE(Expression::Default())
      39             : #define CHECK_OK_VOID CHECK_OK_VALUE(this->Void())
      40             : 
      41             : namespace {
      42             : 
      43    86448196 : PreParserIdentifier GetSymbolHelper(Scanner* scanner) {
      44             :   // These symbols require slightly different treatement:
      45             :   // - regular keywords (async, await, etc.; treated in 1st switch.)
      46             :   // - 'contextual' keywords (and may contain escaped; treated in 2nd switch.)
      47             :   // - 'contextual' keywords, but may not be escaped (3rd switch).
      48    43240864 :   switch (scanner->current_token()) {
      49             :     case Token::AWAIT:
      50             :       return PreParserIdentifier::Await();
      51             :     case Token::ASYNC:
      52             :       return PreParserIdentifier::Async();
      53             :     default:
      54             :       break;
      55             :   }
      56    43207332 :   switch (scanner->current_contextual_token()) {
      57             :     case Token::CONSTRUCTOR:
      58             :       return PreParserIdentifier::Constructor();
      59             :     case Token::NAME:
      60             :       return PreParserIdentifier::Name();
      61             :     default:
      62             :       break;
      63             :   }
      64    42343636 :   if (scanner->literal_contains_escapes()) {
      65             :     return PreParserIdentifier::Default();
      66             :   }
      67    42340596 :   switch (scanner->current_contextual_token()) {
      68             :     case Token::EVAL:
      69             :       return PreParserIdentifier::Eval();
      70             :     case Token::ARGUMENTS:
      71             :       return PreParserIdentifier::Arguments();
      72             :     default:
      73             :       break;
      74             :   }
      75             :   return PreParserIdentifier::Default();
      76             : }
      77             : 
      78             : }  // unnamed namespace
      79             : 
      80    43240864 : PreParserIdentifier PreParser::GetSymbol() const {
      81    84526221 :   PreParserIdentifier symbol = GetSymbolHelper(scanner());
      82    43240864 :   if (track_unresolved_variables_) {
      83    41285357 :     const AstRawString* result = scanner()->CurrentSymbol(ast_value_factory());
      84             :     DCHECK_NOT_NULL(result);
      85             :     symbol.string_ = result;
      86             :   }
      87    43240864 :   return symbol;
      88             : }
      89             : 
      90      436519 : PreParser::PreParseResult PreParser::PreParseProgram(bool is_module) {
      91             :   DCHECK_NULL(scope_);
      92     1578162 :   DeclarationScope* scope = NewScriptScope();
      93             : #ifdef DEBUG
      94             :   scope->set_is_being_lazily_parsed(true);
      95             : #endif
      96             : 
      97             :   // ModuleDeclarationInstantiation for Source Text Module Records creates a
      98             :   // new Module Environment Record whose outer lexical environment record is
      99             :   // the global scope.
     100      436519 :   if (is_module) scope = NewModuleScope(scope);
     101             : 
     102      436519 :   FunctionState top_scope(&function_state_, &scope_, scope);
     103      436519 :   original_scope_ = scope_;
     104      436519 :   bool ok = true;
     105             :   int start_position = scanner()->peek_location().beg_pos;
     106      436519 :   parsing_module_ = is_module;
     107             :   PreParserStatementList body;
     108             :   ParseStatementList(body, Token::EOS, &ok);
     109      436519 :   original_scope_ = nullptr;
     110      436519 :   if (stack_overflow()) return kPreParseStackOverflow;
     111      436514 :   if (!ok) {
     112      207425 :     ReportUnexpectedToken(scanner()->current_token());
     113      229089 :   } else if (is_strict(language_mode())) {
     114       61180 :     CheckStrictOctalLiteral(start_position, scanner()->location().end_pos, &ok);
     115             :   }
     116             :   return kPreParseSuccess;
     117             : }
     118             : 
     119     2234348 : PreParser::PreParseResult PreParser::PreParseFunction(
     120             :     const AstRawString* function_name, FunctionKind kind,
     121             :     FunctionLiteral::FunctionType function_type,
     122             :     DeclarationScope* function_scope, bool parsing_module,
     123             :     bool is_inner_function, bool may_abort, int* use_counts,
     124     2198511 :     ProducedPreParsedScopeData** produced_preparsed_scope_data) {
     125             :   DCHECK_EQ(FUNCTION_SCOPE, function_scope->scope_type());
     126     2234348 :   parsing_module_ = parsing_module;
     127     2234348 :   use_counts_ = use_counts;
     128             :   DCHECK(!track_unresolved_variables_);
     129     2234348 :   track_unresolved_variables_ = is_inner_function;
     130             : #ifdef DEBUG
     131             :   function_scope->set_is_being_lazily_parsed(true);
     132             : #endif
     133             : 
     134             :   // Start collecting data for a new function which might contain skippable
     135             :   // functions.
     136             :   std::unique_ptr<ProducedPreParsedScopeData::DataGatheringScope>
     137             :       produced_preparsed_scope_data_scope;
     138     4468696 :   if (FLAG_preparser_scope_analysis && !IsArrowFunction(kind)) {
     139     2210381 :     track_unresolved_variables_ = true;
     140             :     produced_preparsed_scope_data_scope.reset(
     141             :         new ProducedPreParsedScopeData::DataGatheringScope(function_scope,
     142     2210381 :                                                            this));
     143             :   }
     144             : 
     145             :   // In the preparser, we use the function literal ids to count how many
     146             :   // FunctionLiterals were encountered. The PreParser doesn't actually persist
     147             :   // FunctionLiterals, so there IDs don't matter.
     148     7410461 :   ResetFunctionLiteralId();
     149             : 
     150             :   // The caller passes the function_scope which is not yet inserted into the
     151             :   // scope stack. All scopes above the function_scope are ignored by the
     152             :   // PreParser.
     153             :   DCHECK_NULL(function_state_);
     154             :   DCHECK_NULL(scope_);
     155     2234348 :   FunctionState function_state(&function_state_, &scope_, function_scope);
     156             :   // This indirection is needed so that we can use the CHECK_OK macros.
     157     2234348 :   bool ok_holder = true;
     158             :   bool* ok = &ok_holder;
     159             : 
     160             :   PreParserFormalParameters formals(function_scope);
     161             :   DuplicateFinder duplicate_finder;
     162             :   std::unique_ptr<ExpressionClassifier> formals_classifier;
     163             : 
     164             :   // Parse non-arrow function parameters. For arrow functions, the parameters
     165             :   // have already been parsed.
     166     2234348 :   if (!IsArrowFunction(kind)) {
     167     2210381 :     formals_classifier.reset(new ExpressionClassifier(this, &duplicate_finder));
     168             :     // We return kPreParseSuccess in failure cases too - errors are retrieved
     169             :     // separately by Parser::SkipLazyFunctionBody.
     170     2210381 :     ParseFormalParameterList(&formals, CHECK_OK_VALUE(kPreParseSuccess));
     171     2199960 :     Expect(Token::RPAREN, CHECK_OK_VALUE(kPreParseSuccess));
     172             :     int formals_end_position = scanner()->location().end_pos;
     173             : 
     174             :     CheckArityRestrictions(
     175             :         formals.arity, kind, formals.has_rest, function_scope->start_position(),
     176     2849002 :         formals_end_position, CHECK_OK_VALUE(kPreParseSuccess));
     177             :   }
     178             : 
     179     2222747 :   Expect(Token::LBRACE, CHECK_OK_VALUE(kPreParseSuccess));
     180             :   DeclarationScope* inner_scope = function_scope;
     181             :   LazyParsingResult result;
     182             : 
     183     2222527 :   if (!formals.is_simple) {
     184       70235 :     inner_scope = NewVarblockScope();
     185             :     inner_scope->set_start_position(scanner()->location().beg_pos);
     186             :   }
     187             : 
     188             :   {
     189             :     BlockState block_state(&scope_, inner_scope);
     190     2222527 :     result = ParseStatementListAndLogFunction(&formals, may_abort, ok);
     191             :   }
     192             : 
     193     2222527 :   if (!formals.is_simple) {
     194       70235 :     BuildParameterInitializationBlock(formals, ok);
     195             : 
     196       70235 :     if (is_sloppy(inner_scope->language_mode())) {
     197       55469 :       inner_scope->HoistSloppyBlockFunctions(nullptr);
     198             :     }
     199             : 
     200             :     SetLanguageMode(function_scope, inner_scope->language_mode());
     201             :     inner_scope->set_end_position(scanner()->peek_location().end_pos);
     202       70235 :     inner_scope->FinalizeBlockScope();
     203             :   } else {
     204     2152292 :     if (is_sloppy(function_scope->language_mode())) {
     205     1492206 :       function_scope->HoistSloppyBlockFunctions(nullptr);
     206             :     }
     207             :   }
     208             : 
     209     2222527 :   if (!IsArrowFunction(kind) && track_unresolved_variables_ &&
     210             :       result == kLazyParsingComplete) {
     211             :     CreateFunctionNameAssignment(function_name, function_type, function_scope);
     212             : 
     213             :     // Declare arguments after parsing the function since lexical 'arguments'
     214             :     // masks the arguments object. Declare arguments before declaring the
     215             :     // function var since the arguments object masks 'function arguments'.
     216     2198511 :     function_scope->DeclareArguments(ast_value_factory());
     217             :   }
     218             : 
     219     2222527 :   use_counts_ = nullptr;
     220     2222527 :   track_unresolved_variables_ = false;
     221             : 
     222     2222527 :   if (result == kLazyParsingAborted) {
     223             :     return kPreParseAbort;
     224     2222478 :   } else if (stack_overflow()) {
     225             :     return kPreParseStackOverflow;
     226     2222453 :   } else if (!*ok) {
     227             :     DCHECK(pending_error_handler_->has_pending_error());
     228             :   } else {
     229             :     DCHECK_EQ(Token::RBRACE, scanner()->peek());
     230             : 
     231     2185060 :     if (!IsArrowFunction(kind)) {
     232             :       // Validate parameter names. We can do this only after parsing the
     233             :       // function, since the function can declare itself strict.
     234             :       const bool allow_duplicate_parameters =
     235     3621365 :           is_sloppy(function_scope->language_mode()) && formals.is_simple &&
     236             :           !IsConciseMethod(kind);
     237             :       ValidateFormalParameters(function_scope->language_mode(),
     238             :                                allow_duplicate_parameters,
     239     4326566 :                                CHECK_OK_VALUE(kPreParseSuccess));
     240             : 
     241     2161737 :       *produced_preparsed_scope_data = produced_preparsed_scope_data_;
     242             :     }
     243             : 
     244     2183514 :     if (is_strict(function_scope->language_mode())) {
     245             :       int end_pos = scanner()->location().end_pos;
     246      649721 :       CheckStrictOctalLiteral(function_scope->start_position(), end_pos, ok);
     247             :     }
     248             :   }
     249             :   return kPreParseSuccess;
     250             : }
     251             : 
     252             : 
     253             : // Preparsing checks a JavaScript program and emits preparse-data that helps
     254             : // a later parsing to be faster.
     255             : // See preparser-data.h for the data.
     256             : 
     257             : // The PreParser checks that the syntax follows the grammar for JavaScript,
     258             : // and collects some information about the program along the way.
     259             : // The grammar check is only performed in order to understand the program
     260             : // sufficiently to deduce some information about it, that can be used
     261             : // to speed up later parsing. Finding errors is not the goal of pre-parsing,
     262             : // rather it is to speed up properly written and correct programs.
     263             : // That means that contextual checks (like a label being declared where
     264             : // it is used) are generally omitted.
     265             : 
     266      386442 : PreParser::Expression PreParser::ParseFunctionLiteral(
     267             :     Identifier function_name, Scanner::Location function_name_location,
     268             :     FunctionNameValidity function_name_validity, FunctionKind kind,
     269             :     int function_token_pos, FunctionLiteral::FunctionType function_type,
     270             :     LanguageMode language_mode, bool* ok) {
     271             :   // Function ::
     272             :   //   '(' FormalParameterList? ')' '{' FunctionBody '}'
     273             :   const RuntimeCallStats::CounterId counters[2][2] = {
     274             :       {&RuntimeCallStats::PreParseBackgroundNoVariableResolution,
     275             :        &RuntimeCallStats::PreParseNoVariableResolution},
     276             :       {&RuntimeCallStats::PreParseBackgroundWithVariableResolution,
     277      386442 :        &RuntimeCallStats::PreParseWithVariableResolution}};
     278             :   RuntimeCallTimerScope runtime_timer(
     279             :       runtime_call_stats_,
     280      386442 :       counters[track_unresolved_variables_][parsing_on_main_thread_]);
     281             : 
     282     1625659 :   DeclarationScope* function_scope = NewFunctionScope(kind);
     283           0 :   function_scope->SetLanguageMode(language_mode);
     284             : 
     285             :   // Start collecting data for a new function which might contain skippable
     286             :   // functions.
     287             :   std::unique_ptr<ProducedPreParsedScopeData::DataGatheringScope>
     288             :       produced_preparsed_scope_data_scope;
     289      736912 :   if (!function_state_->next_function_is_likely_called() &&
     290      350470 :       produced_preparsed_scope_data_ != nullptr) {
     291             :     DCHECK(FLAG_preparser_scope_analysis);
     292             :     DCHECK(track_unresolved_variables_);
     293             :     produced_preparsed_scope_data_scope.reset(
     294             :         new ProducedPreParsedScopeData::DataGatheringScope(function_scope,
     295      151280 :                                                            this));
     296             :   }
     297             : 
     298      386442 :   FunctionState function_state(&function_state_, &scope_, function_scope);
     299             :   DuplicateFinder duplicate_finder;
     300      386442 :   ExpressionClassifier formals_classifier(this, &duplicate_finder);
     301             :   int func_id = GetNextFunctionLiteralId();
     302             : 
     303      386442 :   Expect(Token::LPAREN, CHECK_OK);
     304             :   int start_position = scanner()->location().beg_pos;
     305             :   function_scope->set_start_position(start_position);
     306             :   PreParserFormalParameters formals(function_scope);
     307      383776 :   ParseFormalParameterList(&formals, CHECK_OK);
     308      361795 :   Expect(Token::RPAREN, CHECK_OK);
     309             :   int formals_end_position = scanner()->location().end_pos;
     310             : 
     311             :   CheckArityRestrictions(formals.arity, kind, formals.has_rest, start_position,
     312      360466 :                          formals_end_position, CHECK_OK);
     313             : 
     314      359476 :   Expect(Token::LBRACE, CHECK_OK);
     315             : 
     316             :   // Parse function body.
     317             :   PreParserStatementList body;
     318             :   int pos = function_token_pos == kNoSourcePosition ? peek_position()
     319      359116 :                                                     : function_token_pos;
     320             :   ParseFunctionBody(body, function_name, pos, formals, kind, function_type,
     321      359116 :                     CHECK_OK);
     322             : 
     323             :   // Parsing the body may change the language mode in our scope.
     324             :   language_mode = function_scope->language_mode();
     325             : 
     326      291857 :   if (is_sloppy(language_mode)) {
     327      163799 :     function_scope->HoistSloppyBlockFunctions(nullptr);
     328             :   }
     329             : 
     330             :   // Validate name and parameter names. We can do this only after parsing the
     331             :   // function, since the function can declare itself strict.
     332             :   CheckFunctionName(language_mode, function_name, function_name_validity,
     333      291857 :                     function_name_location, CHECK_OK);
     334             :   const bool allow_duplicate_parameters =
     335      445146 :       is_sloppy(language_mode) && formals.is_simple && !IsConciseMethod(kind);
     336      290296 :   ValidateFormalParameters(language_mode, allow_duplicate_parameters, CHECK_OK);
     337             : 
     338             :   int end_position = scanner()->location().end_pos;
     339      288004 :   if (is_strict(language_mode)) {
     340      125075 :     CheckStrictOctalLiteral(start_position, end_position, CHECK_OK);
     341             :   }
     342             : 
     343      287949 :   if (produced_preparsed_scope_data_scope) {
     344             :     produced_preparsed_scope_data_scope->MarkFunctionAsSkippable(
     345      146305 :         end_position, GetLastFunctionLiteralId() - func_id);
     346             :   }
     347      287949 :   if (FLAG_trace_preparse) {
     348             :     PrintF("  [%s]: %i-%i\n",
     349             :            track_unresolved_variables_ ? "Preparse resolution"
     350             :                                        : "Preparse no-resolution",
     351           0 :            function_scope->start_position(), function_scope->end_position());
     352             :   }
     353             : 
     354             :   return Expression::Default();
     355             : }
     356             : 
     357     2222527 : PreParser::LazyParsingResult PreParser::ParseStatementListAndLogFunction(
     358             :     PreParserFormalParameters* formals, bool may_abort, bool* ok) {
     359             :   PreParserStatementList body;
     360             :   LazyParsingResult result = ParseStatementList(
     361     4407587 :       body, Token::RBRACE, may_abort, CHECK_OK_VALUE(kLazyParsingComplete));
     362     2185109 :   if (result == kLazyParsingAborted) return result;
     363             : 
     364             :   // Position right after terminal '}'.
     365             :   DCHECK_EQ(Token::RBRACE, scanner()->peek());
     366             :   int body_end = scanner()->peek_location().end_pos;
     367             :   DCHECK_EQ(this->scope()->is_function_scope(), formals->is_simple);
     368             :   log_.LogFunction(body_end, formals->num_parameters(),
     369     2185060 :                    GetLastFunctionLiteralId());
     370     2185060 :   return kLazyParsingComplete;
     371             : }
     372             : 
     373       89305 : PreParserStatement PreParser::BuildParameterInitializationBlock(
     374             :     const PreParserFormalParameters& parameters, bool* ok) {
     375             :   DCHECK(!parameters.is_simple);
     376             :   DCHECK(scope()->is_function_scope());
     377      178610 :   if (FLAG_preparser_scope_analysis &&
     378       89803 :       scope()->AsDeclarationScope()->calls_sloppy_eval() &&
     379         990 :       produced_preparsed_scope_data_ != nullptr) {
     380             :     // We cannot replicate the Scope structure constructed by the Parser,
     381             :     // because we've lost information whether each individual parameter was
     382             :     // simple or not. Give up trying to produce data to skip inner functions.
     383         984 :     if (produced_preparsed_scope_data_->parent() != nullptr) {
     384             :       // Lazy parsing started before the current function; the function which
     385             :       // cannot contain skippable functions is the parent function. (Its inner
     386             :       // functions cannot either; they are implicitly bailed out.)
     387             :       produced_preparsed_scope_data_->parent()->Bailout();
     388             :     } else {
     389             :       // Lazy parsing started at the current function; it cannot contain
     390             :       // skippable functions.
     391             :       produced_preparsed_scope_data_->Bailout();
     392             :     }
     393             :   }
     394             : 
     395       89305 :   return PreParserStatement::Default();
     396             : }
     397             : 
     398    35019270 : PreParserExpression PreParser::ExpressionFromIdentifier(
     399    35019270 :     const PreParserIdentifier& name, int start_position, InferName infer) {
     400             :   VariableProxy* proxy = nullptr;
     401    35019270 :   if (track_unresolved_variables_) {
     402             :     DCHECK_NOT_NULL(name.string_);
     403             :     proxy = scope()->NewUnresolved(factory()->ast_node_factory(), name.string_,
     404    68462095 :                                    start_position, NORMAL_VARIABLE);
     405             :   }
     406    35019270 :   return PreParserExpression::FromIdentifier(name, proxy, zone());
     407             : }
     408             : 
     409     4307857 : void PreParser::DeclareAndInitializeVariables(
     410             :     PreParserStatement block,
     411             :     const DeclarationDescriptor* declaration_descriptor,
     412             :     const DeclarationParsingResult::Declaration* declaration,
     413             :     ZoneList<const AstRawString*>* names, bool* ok) {
     414     4307857 :   if (declaration->pattern.variables_ != nullptr) {
     415             :     DCHECK(FLAG_lazy_inner_functions);
     416             :     DCHECK(track_unresolved_variables_);
     417    12037701 :     for (auto variable : *(declaration->pattern.variables_)) {
     418     4036591 :       declaration_descriptor->scope->RemoveUnresolved(variable);
     419             :       Variable* var = scope()->DeclareVariableName(
     420     8165620 :           variable->raw_name(), declaration_descriptor->mode);
     421     4036591 :       if (FLAG_preparser_scope_analysis) {
     422             :         MarkLoopVariableAsAssigned(declaration_descriptor->scope, var,
     423     4036591 :                                    declaration_descriptor->declaration_kind);
     424             :         // This is only necessary if there is an initializer, but we don't have
     425             :         // that information here.  Consequently, the preparser sometimes says
     426             :         // maybe-assigned where the parser (correctly) says never-assigned.
     427             :       }
     428     4036591 :       if (names) {
     429       92438 :         names->Add(variable->raw_name(), zone());
     430             :       }
     431             :     }
     432             :   }
     433     4307857 : }
     434             : 
     435             : #undef CHECK_OK
     436             : #undef CHECK_OK_CUSTOM
     437             : 
     438             : 
     439             : }  // namespace internal
     440             : }  // namespace v8

Generated by: LCOV version 1.10