LCOV - code coverage report
Current view: top level - src/parsing - preparser.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 124 126 98.4 %
Date: 2019-02-19 Functions: 11 12 91.7 %

          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/parser-base.h"
      13             : #include "src/parsing/preparse-data.h"
      14             : #include "src/parsing/preparser.h"
      15             : #include "src/unicode.h"
      16             : #include "src/utils.h"
      17             : #include "src/zone/zone-list-inl.h"
      18             : 
      19             : namespace v8 {
      20             : namespace internal {
      21             : 
      22             : namespace {
      23             : 
      24    51498785 : PreParserIdentifier GetSymbolHelper(Scanner* scanner,
      25             :                                     const AstRawString* string,
      26    51431011 :                                     AstValueFactory* avf) {
      27             :   // These symbols require slightly different treatement:
      28             :   // - regular keywords (async, await, etc.; treated in 1st switch.)
      29             :   // - 'contextual' keywords (and may contain escaped; treated in 2nd switch.)
      30             :   // - 'contextual' keywords, but may not be escaped (3rd switch).
      31    51498785 :   switch (scanner->current_token()) {
      32             :     case Token::AWAIT:
      33             :       return PreParserIdentifier::Await();
      34             :     case Token::ASYNC:
      35             :       return PreParserIdentifier::Async();
      36             :     case Token::PRIVATE_NAME:
      37             :       return PreParserIdentifier::PrivateName();
      38             :     default:
      39             :       break;
      40             :   }
      41    51431011 :   if (string == avf->constructor_string()) {
      42             :     return PreParserIdentifier::Constructor();
      43             :   }
      44    51367165 :   if (string == avf->name_string()) {
      45             :     return PreParserIdentifier::Name();
      46             :   }
      47    50461248 :   if (scanner->literal_contains_escapes()) {
      48             :     return PreParserIdentifier::Default();
      49             :   }
      50    50457764 :   if (string == avf->eval_string()) {
      51             :     return PreParserIdentifier::Eval();
      52             :   }
      53    50359528 :   if (string == avf->arguments_string()) {
      54             :     return PreParserIdentifier::Arguments();
      55             :   }
      56             :   return PreParserIdentifier::Default();
      57             : }
      58             : 
      59             : }  // unnamed namespace
      60             : 
      61    51473448 : PreParserIdentifier PreParser::GetSymbol() const {
      62    51473448 :   const AstRawString* result = scanner()->CurrentSymbol(ast_value_factory());
      63             :   PreParserIdentifier symbol =
      64    51496982 :       GetSymbolHelper(scanner(), result, ast_value_factory());
      65             :   DCHECK_NOT_NULL(result);
      66             :   symbol.string_ = result;
      67    51496831 :   return symbol;
      68             : }
      69             : 
      70      520319 : PreParser::PreParseResult PreParser::PreParseProgram() {
      71             :   DCHECK_NULL(scope_);
      72     1188378 :   DeclarationScope* scope = NewScriptScope();
      73             : #ifdef DEBUG
      74             :   scope->set_is_being_lazily_parsed(true);
      75             : #endif
      76             : 
      77      520319 :   if (FLAG_harmony_hashbang) {
      78             :     // Note: We should only skip the hashbang in non-Eval scripts
      79             :     // (currently, Eval is not handled by the PreParser).
      80        9720 :     scanner()->SkipHashBang();
      81             :   }
      82             : 
      83             :   // ModuleDeclarationInstantiation for Source Text Module Records creates a
      84             :   // new Module Environment Record whose outer lexical environment record is
      85             :   // the global scope.
      86      520319 :   if (parsing_module_) scope = NewModuleScope(scope);
      87             : 
      88      520319 :   FunctionState top_scope(&function_state_, &scope_, scope);
      89      520319 :   original_scope_ = scope_;
      90             :   int start_position = peek_position();
      91             :   PreParserScopedStatementList body(pointer_buffer());
      92             :   ParseStatementList(&body, Token::EOS);
      93      520319 :   CheckConflictingVarDeclarations(scope);
      94      520319 :   original_scope_ = nullptr;
      95      520319 :   if (stack_overflow()) return kPreParseStackOverflow;
      96      520314 :   if (is_strict(language_mode())) {
      97      138020 :     CheckStrictOctalLiteral(start_position, scanner()->location().end_pos);
      98             :   }
      99             :   return kPreParseSuccess;
     100             : }
     101             : 
     102     1000347 : void PreParserFormalParameters::ValidateDuplicate(PreParser* preparser) const {
     103     1000347 :   if (has_duplicate_) preparser->ReportUnidentifiableError();
     104     1000346 : }
     105             : 
     106      887425 : void PreParserFormalParameters::ValidateStrictMode(PreParser* preparser) const {
     107      887425 :   if (strict_parameter_error_) preparser->ReportUnidentifiableError();
     108      887425 : }
     109             : 
     110     2510039 : PreParser::PreParseResult PreParser::PreParseFunction(
     111             :     const AstRawString* function_name, FunctionKind kind,
     112             :     FunctionLiteral::FunctionType function_type,
     113             :     DeclarationScope* function_scope, int* use_counts,
     114     2452519 :     ProducedPreparseData** produced_preparse_data, int script_id) {
     115             :   DCHECK_EQ(FUNCTION_SCOPE, function_scope->scope_type());
     116     2510039 :   use_counts_ = use_counts;
     117     5591756 :   set_script_id(script_id);
     118             : #ifdef DEBUG
     119             :   function_scope->set_is_being_lazily_parsed(true);
     120             : #endif
     121             : 
     122             :   PreParserFormalParameters formals(function_scope);
     123             : 
     124             :   // In the preparser, we use the function literal ids to count how many
     125             :   // FunctionLiterals were encountered. The PreParser doesn't actually persist
     126             :   // FunctionLiterals, so there IDs don't matter.
     127             :   ResetFunctionLiteralId();
     128             : 
     129             :   // The caller passes the function_scope which is not yet inserted into the
     130             :   // scope stack. All scopes above the function_scope are ignored by the
     131             :   // PreParser.
     132             :   DCHECK_NULL(function_state_);
     133             :   DCHECK_NULL(scope_);
     134     2510039 :   FunctionState function_state(&function_state_, &scope_, function_scope);
     135             : 
     136             :   // Start collecting data for a new function which might contain skippable
     137             :   // functions.
     138             :   PreparseDataBuilder::DataGatheringScope preparse_data_builder_scope(this);
     139             : 
     140     2510039 :   if (IsArrowFunction(kind)) {
     141       30180 :     formals.is_simple = function_scope->has_simple_parameters();
     142             :   } else {
     143     2479859 :     preparse_data_builder_scope.Start(function_scope);
     144             : 
     145             :     // Parse non-arrow function parameters. For arrow functions, the parameters
     146             :     // have already been parsed.
     147             :     ParameterDeclarationParsingScope formals_scope(this);
     148             :     // We return kPreParseSuccess in failure cases too - errors are retrieved
     149             :     // separately by Parser::SkipLazyFunctionBody.
     150     2479773 :     ParseFormalParameterList(&formals);
     151     2479775 :     if (formals_scope.has_duplicate()) formals.set_has_duplicate();
     152     2479775 :     if (!formals.is_simple) {
     153      106794 :       BuildParameterInitializationBlock(formals);
     154             :     }
     155             : 
     156     2479775 :     Expect(Token::RPAREN);
     157     2479897 :     int formals_end_position = scanner()->location().end_pos;
     158             : 
     159             :     CheckArityRestrictions(formals.arity, kind, formals.has_rest,
     160             :                            function_scope->start_position(),
     161     2952218 :                            formals_end_position);
     162             :   }
     163             : 
     164     2510047 :   Expect(Token::LBRACE);
     165             :   DeclarationScope* inner_scope = function_scope;
     166             : 
     167     2510136 :   if (!formals.is_simple) {
     168      112981 :     inner_scope = NewVarblockScope();
     169             :     inner_scope->set_start_position(position());
     170             :   }
     171             : 
     172             :   {
     173             :     BlockState block_state(&scope_, inner_scope);
     174     2510144 :     ParseStatementListAndLogFunction(&formals);
     175             :   }
     176             : 
     177             :   bool allow_duplicate_parameters = false;
     178     2510066 :   CheckConflictingVarDeclarations(inner_scope);
     179             : 
     180     2510068 :   if (!has_error()) {
     181     2452477 :     if (formals.is_simple) {
     182     2352785 :       if (is_sloppy(function_scope->language_mode())) {
     183     1901865 :         function_scope->HoistSloppyBlockFunctions(nullptr);
     184             :       }
     185             : 
     186             :       allow_duplicate_parameters =
     187     4254499 :           is_sloppy(function_scope->language_mode()) && !IsConciseMethod(kind);
     188             :     } else {
     189       99692 :       if (is_sloppy(inner_scope->language_mode())) {
     190       77205 :         inner_scope->HoistSloppyBlockFunctions(nullptr);
     191             :       }
     192             : 
     193             :       SetLanguageMode(function_scope, inner_scope->language_mode());
     194       99699 :       inner_scope->set_end_position(scanner()->peek_location().end_pos);
     195       99699 :       if (inner_scope->FinalizeBlockScope() != nullptr) {
     196             :         const AstRawString* conflict = inner_scope->FindVariableDeclaredIn(
     197       76970 :             function_scope, VariableMode::kLastLexicalVariableMode);
     198       76975 :         if (conflict != nullptr)
     199             :           ReportVarRedeclarationIn(conflict, inner_scope);
     200             :       }
     201             :     }
     202             :   }
     203             : 
     204     2510029 :   use_counts_ = nullptr;
     205             : 
     206     2510029 :   if (stack_overflow()) {
     207             :     return kPreParseStackOverflow;
     208     2510060 :   } else if (pending_error_handler()->has_error_unidentifiable_by_preparser()) {
     209             :     return kPreParseNotIdentifiableError;
     210     2463453 :   } else if (has_error()) {
     211             :     DCHECK(pending_error_handler()->has_pending_error());
     212             :   } else {
     213             :     DCHECK_EQ(Token::RBRACE, scanner()->peek());
     214             : 
     215     2452483 :     if (!IsArrowFunction(kind)) {
     216             :       // Validate parameter names. We can do this only after parsing the
     217             :       // function, since the function can declare itself strict.
     218             :       ValidateFormalParameters(language_mode(), formals,
     219     4856506 :                                allow_duplicate_parameters);
     220     2428315 :       if (has_error()) {
     221        1465 :         if (pending_error_handler()->has_error_unidentifiable_by_preparser()) {
     222             :           return kPreParseNotIdentifiableError;
     223             :         } else {
     224           0 :           return kPreParseSuccess;
     225             :         }
     226             :       }
     227             : 
     228             :       // Declare arguments after parsing the function since lexical
     229             :       // 'arguments' masks the arguments object. Declare arguments before
     230             :       // declaring the function var since the arguments object masks 'function
     231             :       // arguments'.
     232     2426850 :       function_scope->DeclareArguments(ast_value_factory());
     233             : 
     234             :       DeclareFunctionNameVar(function_name, function_type, function_scope);
     235             : 
     236     2426850 :       if (preparse_data_builder_->HasData()) {
     237             :         *produced_preparse_data =
     238       84106 :             ProducedPreparseData::For(preparse_data_builder_, main_zone());
     239             :       }
     240             :     }
     241             : 
     242     2451054 :     if (pending_error_handler()->has_error_unidentifiable_by_preparser()) {
     243             :       return kPreParseNotIdentifiableError;
     244             :     }
     245             : 
     246     2451036 :     if (is_strict(function_scope->language_mode())) {
     247      472321 :       int end_pos = scanner()->location().end_pos;
     248      472321 :       CheckStrictOctalLiteral(function_scope->start_position(), end_pos);
     249             :     }
     250             :   }
     251             : 
     252             :   DCHECK(!pending_error_handler()->has_error_unidentifiable_by_preparser());
     253             :   return kPreParseSuccess;
     254             : }
     255             : 
     256             : // Preparsing checks a JavaScript program and emits preparse-data that helps
     257             : // a later parsing to be faster.
     258             : // See preparser-data.h for the data.
     259             : 
     260             : // The PreParser checks that the syntax follows the grammar for JavaScript,
     261             : // and collects some information about the program along the way.
     262             : // The grammar check is only performed in order to understand the program
     263             : // sufficiently to deduce some information about it, that can be used
     264             : // to speed up later parsing. Finding errors is not the goal of pre-parsing,
     265             : // rather it is to speed up properly written and correct programs.
     266             : // That means that contextual checks (like a label being declared where
     267             : // it is used) are generally omitted.
     268             : 
     269      421637 : PreParser::Expression PreParser::ParseFunctionLiteral(
     270      421667 :     Identifier function_name, Scanner::Location function_name_location,
     271             :     FunctionNameValidity function_name_validity, FunctionKind kind,
     272             :     int function_token_pos, FunctionLiteral::FunctionType function_type,
     273             :     LanguageMode language_mode,
     274             :     ZonePtrList<const AstRawString>* arguments_for_wrapped_function) {
     275             :   // Wrapped functions are not parsed in the preparser.
     276             :   DCHECK_NULL(arguments_for_wrapped_function);
     277             :   DCHECK_NE(FunctionLiteral::kWrapped, function_type);
     278             :   // Function ::
     279             :   //   '(' FormalParameterList? ')' '{' FunctionBody '}'
     280             :   const RuntimeCallCounterId counters[2] = {
     281             :       RuntimeCallCounterId::kPreParseBackgroundWithVariableResolution,
     282      421637 :       RuntimeCallCounterId::kPreParseWithVariableResolution};
     283             :   RuntimeCallTimerScope runtime_timer(runtime_call_stats_,
     284      421637 :                                       counters[parsing_on_main_thread_]);
     285             : 
     286             :   base::ElapsedTimer timer;
     287      421641 :   if (V8_UNLIKELY(FLAG_log_function_events)) timer.Start();
     288             : 
     289     1621359 :   DeclarationScope* function_scope = NewFunctionScope(kind);
     290           9 :   function_scope->SetLanguageMode(language_mode);
     291             :   int func_id = GetNextFunctionLiteralId();
     292             :   bool skippable_function = false;
     293             : 
     294             :   // Start collecting data for a new function which might contain skippable
     295             :   // functions.
     296             :   {
     297             :     PreparseDataBuilder::DataGatheringScope preparse_data_builder_scope(this);
     298      806652 :     skippable_function = !function_state_->next_function_is_likely_called() &&
     299      384978 :                          preparse_data_builder_ != nullptr;
     300      421674 :     if (skippable_function) {
     301      146892 :       preparse_data_builder_scope.Start(function_scope);
     302             :     }
     303             : 
     304      421673 :     FunctionState function_state(&function_state_, &scope_, function_scope);
     305             : 
     306      421673 :     Expect(Token::LPAREN);
     307             :     int start_position = position();
     308             :     function_scope->set_start_position(start_position);
     309             :     PreParserFormalParameters formals(function_scope);
     310             :     {
     311             :       ParameterDeclarationParsingScope formals_scope(this);
     312      421679 :       ParseFormalParameterList(&formals);
     313      421678 :       if (formals_scope.has_duplicate()) formals.set_has_duplicate();
     314             :     }
     315      421678 :     Expect(Token::RPAREN);
     316      421674 :     int formals_end_position = scanner()->location().end_pos;
     317             : 
     318             :     CheckArityRestrictions(formals.arity, kind, formals.has_rest,
     319      421674 :                            start_position, formals_end_position);
     320             : 
     321      421674 :     Expect(Token::LBRACE);
     322             : 
     323             :     // Parse function body.
     324             :     PreParserScopedStatementList body(pointer_buffer());
     325             :     int pos = function_token_pos == kNoSourcePosition ? peek_position()
     326      421675 :                                                       : function_token_pos;
     327             :     AcceptINScope scope(this, true);
     328             :     ParseFunctionBody(&body, function_name, pos, formals, kind, function_type,
     329      421675 :                       FunctionBodyType::kBlock);
     330             : 
     331             :     // Parsing the body may change the language mode in our scope.
     332             :     language_mode = function_scope->language_mode();
     333             : 
     334      421667 :     if (is_sloppy(language_mode)) {
     335      212193 :       function_scope->HoistSloppyBlockFunctions(nullptr);
     336             :     }
     337             : 
     338             :     // Validate name and parameter names. We can do this only after parsing the
     339             :     // function, since the function can declare itself strict.
     340             :     CheckFunctionName(language_mode, function_name, function_name_validity,
     341      421667 :                       function_name_location);
     342             : 
     343      421658 :     if (is_strict(language_mode)) {
     344      209480 :       CheckStrictOctalLiteral(start_position, end_position());
     345             :     }
     346      421668 :     if (skippable_function) {
     347             :       preparse_data_builder_scope.SetSkippableFunction(
     348      146876 :           function_scope, GetLastFunctionLiteralId() - func_id);
     349             :     }
     350             :   }
     351             : 
     352      421646 :   if (V8_UNLIKELY(FLAG_log_function_events)) {
     353           9 :     double ms = timer.Elapsed().InMillisecondsF();
     354             :     const char* event_name = "preparse-resolution";
     355             :     // We might not always get a function name here. However, it can be easily
     356             :     // reconstructed from the script id and the byte range in the log processor.
     357             :     const char* name = "";
     358             :     size_t name_byte_length = 0;
     359           9 :     const AstRawString* string = function_name.string_;
     360           9 :     if (string != nullptr) {
     361             :       name = reinterpret_cast<const char*>(string->raw_data());
     362           3 :       name_byte_length = string->byte_length();
     363             :     }
     364             :     logger_->FunctionEvent(
     365             :         event_name, script_id(), ms, function_scope->start_position(),
     366           9 :         function_scope->end_position(), name, name_byte_length);
     367             :   }
     368             : 
     369      421646 :   return Expression::Default();
     370             : }
     371             : 
     372     2509990 : void PreParser::ParseStatementListAndLogFunction(
     373             :     PreParserFormalParameters* formals) {
     374     5019348 :   PreParserScopedStatementList body(pointer_buffer());
     375     2509990 :   ParseStatementList(&body, Token::RBRACE);
     376             : 
     377             :   // Position right after terminal '}'.
     378             :   DCHECK_IMPLIES(!has_error(), scanner()->peek() == Token::RBRACE);
     379     2509674 :   int body_end = scanner()->peek_location().end_pos;
     380             :   DCHECK_EQ(this->scope()->is_function_scope(), formals->is_simple);
     381             :   log_.LogFunction(body_end, formals->num_parameters(),
     382     2509674 :                    GetLastFunctionLiteralId());
     383     2509674 : }
     384             : 
     385      128265 : PreParserBlock PreParser::BuildParameterInitializationBlock(
     386             :     const PreParserFormalParameters& parameters) {
     387             :   DCHECK(!parameters.is_simple);
     388             :   DCHECK(scope()->is_function_scope());
     389      257144 :   if (scope()->AsDeclarationScope()->calls_sloppy_eval() &&
     390        1168 :       preparse_data_builder_ != nullptr) {
     391             :     // We cannot replicate the Scope structure constructed by the Parser,
     392             :     // because we've lost information whether each individual parameter was
     393             :     // simple or not. Give up trying to produce data to skip inner functions.
     394        1162 :     if (preparse_data_builder_->parent() != nullptr) {
     395             :       // Lazy parsing started before the current function; the function which
     396             :       // cannot contain skippable functions is the parent function. (Its inner
     397             :       // functions cannot either; they are implicitly bailed out.)
     398             :       preparse_data_builder_->parent()->Bailout();
     399             :     } else {
     400             :       // Lazy parsing started at the current function; it cannot contain
     401             :       // skippable functions.
     402             :       preparse_data_builder_->Bailout();
     403             :     }
     404             :   }
     405             : 
     406      128292 :   return PreParserBlock::Default();
     407             : }
     408             : 
     409           0 : bool PreParser::IdentifierEquals(const PreParserIdentifier& identifier,
     410             :                                  const AstRawString* other) {
     411     1568438 :   return identifier.string_ == other;
     412             : }
     413             : 
     414             : }  // namespace internal
     415      178779 : }  // namespace v8

Generated by: LCOV version 1.10