LCOV - code coverage report
Current view: top level - src/parsing - preparser.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 136 138 98.6 %
Date: 2019-01-20 Functions: 13 14 92.9 %

          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             : 
      18             : namespace v8 {
      19             : namespace internal {
      20             : 
      21             : namespace {
      22             : 
      23    49930130 : PreParserIdentifier GetSymbolHelper(Scanner* scanner,
      24             :                                     const AstRawString* string,
      25    49855417 :                                     AstValueFactory* avf) {
      26             :   // These symbols require slightly different treatement:
      27             :   // - regular keywords (async, await, etc.; treated in 1st switch.)
      28             :   // - 'contextual' keywords (and may contain escaped; treated in 2nd switch.)
      29             :   // - 'contextual' keywords, but may not be escaped (3rd switch).
      30    49930130 :   switch (scanner->current_token()) {
      31             :     case Token::LET:
      32             :       return PreParserIdentifier::Let();
      33             :     case Token::AWAIT:
      34             :       return PreParserIdentifier::Await();
      35             :     case Token::ASYNC:
      36             :       return PreParserIdentifier::Async();
      37             :     case Token::PRIVATE_NAME:
      38             :       return PreParserIdentifier::PrivateName();
      39             :     default:
      40             :       break;
      41             :   }
      42    49855417 :   if (string == avf->constructor_string()) {
      43             :     return PreParserIdentifier::Constructor();
      44             :   }
      45    49791191 :   if (string == avf->name_string()) {
      46             :     return PreParserIdentifier::Name();
      47             :   }
      48    48987559 :   if (scanner->literal_contains_escapes()) {
      49        2932 :     if (string == avf->let_string()) {
      50             :       return PreParserIdentifier::Let();
      51             :     }
      52             :     return PreParserIdentifier::Default();
      53             :   }
      54    48984029 :   if (string == avf->eval_string()) {
      55             :     return PreParserIdentifier::Eval();
      56             :   }
      57    48854932 :   if (string == avf->arguments_string()) {
      58             :     return PreParserIdentifier::Arguments();
      59             :   }
      60             :   return PreParserIdentifier::Default();
      61             : }
      62             : 
      63             : }  // unnamed namespace
      64             : 
      65    49900641 : PreParserIdentifier PreParser::GetSymbol() const {
      66    49900641 :   const AstRawString* result = scanner()->CurrentSymbol(ast_value_factory());
      67             :   PreParserIdentifier symbol =
      68    49928950 :       GetSymbolHelper(scanner(), result, ast_value_factory());
      69             :   DCHECK_NOT_NULL(result);
      70             :   symbol.string_ = result;
      71    49928022 :   return symbol;
      72             : }
      73             : 
      74      509579 : PreParser::PreParseResult PreParser::PreParseProgram() {
      75             :   DCHECK_NULL(scope_);
      76     1156958 :   DeclarationScope* scope = NewScriptScope();
      77             : #ifdef DEBUG
      78             :   scope->set_is_being_lazily_parsed(true);
      79             : #endif
      80             : 
      81      509579 :   if (FLAG_harmony_hashbang) {
      82             :     // Note: We should only skip the hashbang in non-Eval scripts
      83             :     // (currently, Eval is not handled by the PreParser).
      84        4800 :     scanner()->SkipHashBang();
      85             :   }
      86             : 
      87             :   // ModuleDeclarationInstantiation for Source Text Module Records creates a
      88             :   // new Module Environment Record whose outer lexical environment record is
      89             :   // the global scope.
      90      509579 :   if (parsing_module_) scope = NewModuleScope(scope);
      91             : 
      92      509579 :   FunctionState top_scope(&function_state_, &scope_, scope);
      93      509579 :   original_scope_ = scope_;
      94             :   int start_position = peek_position();
      95             :   PreParserScopedStatementList body(pointer_buffer());
      96             :   ParseStatementList(&body, Token::EOS);
      97      509579 :   original_scope_ = nullptr;
      98      509579 :   if (stack_overflow()) return kPreParseStackOverflow;
      99      509574 :   if (is_strict(language_mode())) {
     100      133000 :     CheckStrictOctalLiteral(start_position, scanner()->location().end_pos);
     101             :   }
     102             :   return kPreParseSuccess;
     103             : }
     104             : 
     105     1220953 : void PreParserFormalParameters::ValidateDuplicate(PreParser* preparser) const {
     106     1220953 :   if (has_duplicate_) preparser->ReportUnidentifiableError();
     107     1220953 : }
     108             : 
     109      892973 : void PreParserFormalParameters::ValidateStrictMode(PreParser* preparser) const {
     110      892973 :   if (strict_parameter_error_) preparser->ReportUnidentifiableError();
     111      892973 : }
     112             : 
     113     2446131 : PreParser::PreParseResult PreParser::PreParseFunction(
     114             :     const AstRawString* function_name, FunctionKind kind,
     115             :     FunctionLiteral::FunctionType function_type,
     116             :     DeclarationScope* function_scope, int* use_counts,
     117     2393617 :     ProducedPreparseData** produced_preparse_data, int script_id) {
     118             :   DCHECK_EQ(FUNCTION_SCOPE, function_scope->scope_type());
     119     2446131 :   use_counts_ = use_counts;
     120     5481514 :   set_script_id(script_id);
     121             : #ifdef DEBUG
     122             :   function_scope->set_is_being_lazily_parsed(true);
     123             : #endif
     124             : 
     125             :   PreParserFormalParameters formals(function_scope);
     126             : 
     127             :   // In the preparser, we use the function literal ids to count how many
     128             :   // FunctionLiterals were encountered. The PreParser doesn't actually persist
     129             :   // FunctionLiterals, so there IDs don't matter.
     130             :   ResetFunctionLiteralId();
     131             : 
     132             :   // The caller passes the function_scope which is not yet inserted into the
     133             :   // scope stack. All scopes above the function_scope are ignored by the
     134             :   // PreParser.
     135             :   DCHECK_NULL(function_state_);
     136             :   DCHECK_NULL(scope_);
     137     2446131 :   FunctionState function_state(&function_state_, &scope_, function_scope);
     138             : 
     139             :   // Start collecting data for a new function which might contain skippable
     140             :   // functions.
     141     2446045 :   PreparseDataBuilder::DataGatheringScope preparse_data_builder_scope(this);
     142             : 
     143     2446131 :   if (IsArrowFunction(kind)) {
     144       27210 :     formals.is_simple = function_scope->has_simple_parameters();
     145             :   } else {
     146     2418921 :     preparse_data_builder_scope.Start(function_scope);
     147             : 
     148             :     // Parse non-arrow function parameters. For arrow functions, the parameters
     149             :     // have already been parsed.
     150             :     ParameterDeclarationParsingScope formals_scope(this);
     151             :     // We return kPreParseSuccess in failure cases too - errors are retrieved
     152             :     // separately by Parser::SkipLazyFunctionBody.
     153     2418865 :     ParseFormalParameterList(&formals);
     154     2418822 :     if (!formals.is_simple) {
     155      104277 :       BuildParameterInitializationBlock(formals);
     156             :     }
     157             : 
     158     2418826 :     Expect(Token::RPAREN);
     159     2418945 :     int formals_end_position = scanner()->location().end_pos;
     160             : 
     161             :     CheckArityRestrictions(formals.arity, kind, formals.has_rest,
     162             :                            function_scope->start_position(),
     163     2898484 :                            formals_end_position);
     164             :   }
     165             : 
     166     2445915 :   Expect(Token::LBRACE);
     167             :   DeclarationScope* inner_scope = function_scope;
     168             : 
     169     2446174 :   if (!formals.is_simple) {
     170      107550 :     inner_scope = NewVarblockScope();
     171             :     inner_scope->set_start_position(position());
     172             :   }
     173             : 
     174             :   {
     175             :     BlockState block_state(&scope_, inner_scope);
     176     2446177 :     ParseStatementListAndLogFunction(&formals);
     177             :   }
     178             : 
     179             :   bool allow_duplicate_parameters = false;
     180             : 
     181     2446083 :   if (formals.is_simple) {
     182     2338533 :     if (is_sloppy(function_scope->language_mode())) {
     183     1854196 :       function_scope->HoistSloppyBlockFunctions(nullptr);
     184             :     }
     185             : 
     186     1854155 :     allow_duplicate_parameters = is_sloppy(function_scope->language_mode()) &&
     187     4178680 :                                  !IsConciseMethod(kind) &&
     188             :                                  !IsArrowFunction(kind);
     189             :   } else {
     190      107550 :     if (is_sloppy(inner_scope->language_mode())) {
     191       79857 :       inner_scope->HoistSloppyBlockFunctions(nullptr);
     192             :     }
     193             : 
     194             :     SetLanguageMode(function_scope, inner_scope->language_mode());
     195      107551 :     inner_scope->set_end_position(scanner()->peek_location().end_pos);
     196      107551 :     if (inner_scope->FinalizeBlockScope() != nullptr) {
     197             :       const AstRawString* conflict = inner_scope->FindVariableDeclaredIn(
     198       74045 :           function_scope, VariableMode::kLastLexicalVariableMode);
     199       74048 :       if (conflict != nullptr) ReportVarRedeclarationIn(conflict, inner_scope);
     200             :     }
     201             :   }
     202             : 
     203     2446117 :   use_counts_ = nullptr;
     204             : 
     205     2446117 :   if (stack_overflow()) {
     206             :     return kPreParseStackOverflow;
     207     2446058 :   } else if (pending_error_handler()->has_error_unidentifiable_by_preparser()) {
     208             :     return kPreParseNotIdentifiableError;
     209     2404591 :   } else if (has_error()) {
     210             :     DCHECK(pending_error_handler()->has_pending_error());
     211             :   } else {
     212             :     DCHECK_EQ(Token::RBRACE, scanner()->peek());
     213             : 
     214     2393657 :     if (!IsArrowFunction(kind)) {
     215             :       // Validate parameter names. We can do this only after parsing the
     216             :       // function, since the function can declare itself strict.
     217             :       ValidateFormalParameters(language_mode(), formals,
     218     4738716 :                                allow_duplicate_parameters);
     219     2369379 :       if (has_error()) {
     220        1453 :         if (pending_error_handler()->has_error_unidentifiable_by_preparser()) {
     221             :           return kPreParseNotIdentifiableError;
     222             :         } else {
     223           0 :           return kPreParseSuccess;
     224             :         }
     225             :       }
     226             : 
     227             :       // Declare arguments after parsing the function since lexical
     228             :       // 'arguments' masks the arguments object. Declare arguments before
     229             :       // declaring the function var since the arguments object masks 'function
     230             :       // arguments'.
     231     2367926 :       function_scope->DeclareArguments(ast_value_factory());
     232             : 
     233             :       DeclareFunctionNameVar(function_name, function_type, function_scope);
     234             : 
     235     2367939 :       if (preparse_data_builder_->HasData()) {
     236             :         *produced_preparse_data =
     237       84044 :             ProducedPreparseData::For(preparse_data_builder_, main_zone());
     238             :       }
     239             :     }
     240             : 
     241     2392164 :     if (pending_error_handler()->has_error_unidentifiable_by_preparser()) {
     242             :       return kPreParseNotIdentifiableError;
     243             :     }
     244             : 
     245     2392191 :     if (is_strict(function_scope->language_mode())) {
     246      479539 :       int end_pos = scanner()->location().end_pos;
     247      479539 :       CheckStrictOctalLiteral(function_scope->start_position(), end_pos);
     248             :     }
     249             :   }
     250             : 
     251             :   DCHECK(!pending_error_handler()->has_error_unidentifiable_by_preparser());
     252             :   return kPreParseSuccess;
     253             : }
     254             : 
     255             : // Preparsing checks a JavaScript program and emits preparse-data that helps
     256             : // a later parsing to be faster.
     257             : // See preparser-data.h for the data.
     258             : 
     259             : // The PreParser checks that the syntax follows the grammar for JavaScript,
     260             : // and collects some information about the program along the way.
     261             : // The grammar check is only performed in order to understand the program
     262             : // sufficiently to deduce some information about it, that can be used
     263             : // to speed up later parsing. Finding errors is not the goal of pre-parsing,
     264             : // rather it is to speed up properly written and correct programs.
     265             : // That means that contextual checks (like a label being declared where
     266             : // it is used) are generally omitted.
     267             : 
     268      420159 : PreParser::Expression PreParser::ParseFunctionLiteral(
     269      420163 :     Identifier function_name, Scanner::Location function_name_location,
     270             :     FunctionNameValidity function_name_validity, FunctionKind kind,
     271             :     int function_token_pos, FunctionLiteral::FunctionType function_type,
     272             :     LanguageMode language_mode,
     273             :     ZonePtrList<const AstRawString>* arguments_for_wrapped_function) {
     274             :   // Wrapped functions are not parsed in the preparser.
     275             :   DCHECK_NULL(arguments_for_wrapped_function);
     276             :   DCHECK_NE(FunctionLiteral::kWrapped, function_type);
     277             :   // Function ::
     278             :   //   '(' FormalParameterList? ')' '{' FunctionBody '}'
     279             :   const RuntimeCallCounterId counters[2] = {
     280             :       RuntimeCallCounterId::kPreParseBackgroundWithVariableResolution,
     281      420159 :       RuntimeCallCounterId::kPreParseWithVariableResolution};
     282             :   RuntimeCallTimerScope runtime_timer(runtime_call_stats_,
     283      420159 :                                       counters[parsing_on_main_thread_]);
     284             : 
     285             :   base::ElapsedTimer timer;
     286      420159 :   if (V8_UNLIKELY(FLAG_log_function_events)) timer.Start();
     287             : 
     288     1617475 :   DeclarationScope* function_scope = NewFunctionScope(kind);
     289          12 :   function_scope->SetLanguageMode(language_mode);
     290             :   int func_id = GetNextFunctionLiteralId();
     291             :   bool skippable_function = false;
     292             : 
     293             :   // Start collecting data for a new function which might contain skippable
     294             :   // functions.
     295             :   {
     296             :     PreparseDataBuilder::DataGatheringScope preparse_data_builder_scope(this);
     297      803631 :     skippable_function = !function_state_->next_function_is_likely_called() &&
     298      383450 :                          preparse_data_builder_ != nullptr;
     299      420181 :     if (skippable_function) {
     300      148413 :       preparse_data_builder_scope.Start(function_scope);
     301             :     }
     302             : 
     303      420173 :     FunctionState function_state(&function_state_, &scope_, function_scope);
     304             : 
     305      420173 :     Expect(Token::LPAREN);
     306             :     int start_position = position();
     307             :     function_scope->set_start_position(start_position);
     308             :     PreParserFormalParameters formals(function_scope);
     309             :     {
     310             :       ParameterDeclarationParsingScope formals_scope(this);
     311      420184 :       ParseFormalParameterList(&formals);
     312             :     }
     313      420182 :     Expect(Token::RPAREN);
     314      420184 :     int formals_end_position = scanner()->location().end_pos;
     315             : 
     316             :     CheckArityRestrictions(formals.arity, kind, formals.has_rest,
     317      420184 :                            start_position, formals_end_position);
     318             : 
     319      420181 :     Expect(Token::LBRACE);
     320             : 
     321             :     // Parse function body.
     322             :     PreParserScopedStatementList body(pointer_buffer());
     323             :     int pos = function_token_pos == kNoSourcePosition ? peek_position()
     324      420177 :                                                       : function_token_pos;
     325             :     AcceptINScope scope(this, true);
     326             :     ParseFunctionBody(&body, function_name, pos, formals, kind, function_type,
     327      420177 :                       FunctionBodyType::kBlock);
     328             : 
     329             :     // Parsing the body may change the language mode in our scope.
     330             :     language_mode = function_scope->language_mode();
     331             : 
     332      420163 :     if (is_sloppy(language_mode)) {
     333      211638 :       function_scope->HoistSloppyBlockFunctions(nullptr);
     334             :     }
     335             : 
     336             :     // Validate name and parameter names. We can do this only after parsing the
     337             :     // function, since the function can declare itself strict.
     338             :     CheckFunctionName(language_mode, function_name, function_name_validity,
     339      420163 :                       function_name_location);
     340             : 
     341      420173 :     if (is_strict(language_mode)) {
     342      208535 :       CheckStrictOctalLiteral(start_position, end_position());
     343             :     }
     344      420168 :     if (skippable_function) {
     345             :       preparse_data_builder_scope.SetSkippableFunction(
     346      148401 :           function_scope, GetLastFunctionLiteralId() - func_id);
     347      420156 :     }
     348             :   }
     349             : 
     350      420162 :   if (V8_UNLIKELY(FLAG_log_function_events)) {
     351          12 :     double ms = timer.Elapsed().InMillisecondsF();
     352             :     const char* event_name = "preparse-resolution";
     353             :     // We might not always get a function name here. However, it can be easily
     354             :     // reconstructed from the script id and the byte range in the log processor.
     355             :     const char* name = "";
     356             :     size_t name_byte_length = 0;
     357          12 :     const AstRawString* string = function_name.string_;
     358          12 :     if (string != nullptr) {
     359             :       name = reinterpret_cast<const char*>(string->raw_data());
     360           4 :       name_byte_length = string->byte_length();
     361             :     }
     362             :     logger_->FunctionEvent(
     363             :         event_name, script_id(), ms, function_scope->start_position(),
     364          12 :         function_scope->end_position(), name, name_byte_length);
     365             :   }
     366             : 
     367      420169 :   return Expression::Default();
     368             : }
     369             : 
     370     2445997 : void PreParser::ParseStatementListAndLogFunction(
     371             :     PreParserFormalParameters* formals) {
     372     4890924 :   PreParserScopedStatementList body(pointer_buffer());
     373     2445997 :   ParseStatementList(&body, Token::RBRACE);
     374             : 
     375             :   // Position right after terminal '}'.
     376             :   DCHECK_IMPLIES(!has_error(), scanner()->peek() == Token::RBRACE);
     377     2445462 :   int body_end = scanner()->peek_location().end_pos;
     378             :   DCHECK_EQ(this->scope()->is_function_scope(), formals->is_simple);
     379             :   log_.LogFunction(body_end, formals->num_parameters(),
     380     2445462 :                    GetLastFunctionLiteralId());
     381     2445462 : }
     382             : 
     383      126378 : PreParserBlock PreParser::BuildParameterInitializationBlock(
     384             :     const PreParserFormalParameters& parameters) {
     385             :   DCHECK(!parameters.is_simple);
     386             :   DCHECK(scope()->is_function_scope());
     387      253331 :   if (scope()->AsDeclarationScope()->calls_sloppy_eval() &&
     388        1134 :       preparse_data_builder_ != nullptr) {
     389             :     // We cannot replicate the Scope structure constructed by the Parser,
     390             :     // because we've lost information whether each individual parameter was
     391             :     // simple or not. Give up trying to produce data to skip inner functions.
     392        1128 :     if (preparse_data_builder_->parent() != nullptr) {
     393             :       // Lazy parsing started before the current function; the function which
     394             :       // cannot contain skippable functions is the parent function. (Its inner
     395             :       // functions cannot either; they are implicitly bailed out.)
     396             :       preparse_data_builder_->parent()->Bailout();
     397             :     } else {
     398             :       // Lazy parsing started at the current function; it cannot contain
     399             :       // skippable functions.
     400             :       preparse_data_builder_->Bailout();
     401             :     }
     402             :   }
     403             : 
     404      126383 :   return PreParserBlock::Default();
     405             : }
     406             : 
     407           0 : bool PreParser::IdentifierEquals(const PreParserIdentifier& identifier,
     408             :                                  const AstRawString* other) {
     409     1574991 :   return identifier.string_ == other;
     410             : }
     411             : 
     412    38626006 : PreParserExpression PreParser::ExpressionFromIdentifier(
     413    38599772 :     const PreParserIdentifier& name, int start_position, InferName infer) {
     414             :   DCHECK_IMPLIES(name.string_ == nullptr, has_error());
     415    38626006 :   if (name.string_ == nullptr) return PreParserExpression::Default();
     416             :   VariableProxy* proxy =
     417    38605516 :       expression_scope()->NewVariable(name.string_, start_position);
     418    38599772 :   return PreParserExpression::FromIdentifier(name, proxy, zone());
     419             : }
     420             : 
     421     4941670 : void PreParser::InitializeVariables(
     422             :     PreParserScopedStatementList* statements,
     423             :     const DeclarationDescriptor* declaration_descriptor,
     424             :     const DeclarationParsingResult::Declaration* declaration,
     425             :     ZonePtrList<const AstRawString>* names) {
     426     4941670 :   if (declaration->pattern.variables_ != nullptr) {
     427    14870283 :     for (auto variable : *(declaration->pattern.variables_)) {
     428             :       Variable* var = scope()->DeclareVariableName(
     429    10142102 :           variable->raw_name(), declaration_descriptor->mode);
     430     4987292 :       if (var == nullptr) {
     431             :         ReportUnidentifiableError();
     432     4941816 :         return;
     433             :       }
     434             :       // This is only necessary if there is an initializer, but we don't have
     435             :       // that information here.  Consequently, the preparser sometimes says
     436             :       // maybe-assigned where the parser (correctly) says never-assigned.
     437     4987278 :       if (names) {
     438      167812 :         names->Add(variable->raw_name(), zone());
     439             :       }
     440             :     }
     441             :   }
     442             : }
     443             : 
     444             : }  // namespace internal
     445      183867 : }  // namespace v8

Generated by: LCOV version 1.10