Home | History | Annotate | Download | only in parsing
      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/preparsed-scope-data.h"
     15 #include "src/parsing/preparser.h"
     16 #include "src/unicode.h"
     17 #include "src/utils.h"
     18 
     19 namespace v8 {
     20 namespace internal {
     21 
     22 // ----------------------------------------------------------------------------
     23 // The CHECK_OK macro is a convenient macro to enforce error
     24 // handling for functions that may fail (by returning !*ok).
     25 //
     26 // CAUTION: This macro appends extra statements after a call,
     27 // thus it must never be used where only a single statement
     28 // is correct (e.g. an if statement branch w/o braces)!
     29 
     30 #define CHECK_OK_VALUE(x) ok); \
     31   if (!*ok) return x;          \
     32   ((void)0
     33 #define DUMMY )  // to make indentation work
     34 #undef DUMMY
     35 
     36 #define CHECK_OK CHECK_OK_VALUE(Expression::Default())
     37 #define CHECK_OK_VOID CHECK_OK_VALUE(this->Void())
     38 
     39 namespace {
     40 
     41 PreParserIdentifier GetSymbolHelper(Scanner* scanner) {
     42   // These symbols require slightly different treatement:
     43   // - regular keywords (async, await, etc.; treated in 1st switch.)
     44   // - 'contextual' keywords (and may contain escaped; treated in 2nd switch.)
     45   // - 'contextual' keywords, but may not be escaped (3rd switch).
     46   switch (scanner->current_token()) {
     47     case Token::AWAIT:
     48       return PreParserIdentifier::Await();
     49     case Token::ASYNC:
     50       return PreParserIdentifier::Async();
     51     case Token::PRIVATE_NAME:
     52       return PreParserIdentifier::PrivateName();
     53     default:
     54       break;
     55   }
     56   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   if (scanner->literal_contains_escapes()) {
     65     return PreParserIdentifier::Default();
     66   }
     67   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 PreParserIdentifier PreParser::GetSymbol() const {
     81   PreParserIdentifier symbol = GetSymbolHelper(scanner());
     82   if (track_unresolved_variables_) {
     83     const AstRawString* result = scanner()->CurrentSymbol(ast_value_factory());
     84     DCHECK_NOT_NULL(result);
     85     symbol.string_ = result;
     86   }
     87   return symbol;
     88 }
     89 
     90 PreParser::PreParseResult PreParser::PreParseProgram() {
     91   DCHECK_NULL(scope_);
     92   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   if (parsing_module_) scope = NewModuleScope(scope);
    101 
    102   FunctionState top_scope(&function_state_, &scope_, scope);
    103   original_scope_ = scope_;
    104   bool ok = true;
    105   int start_position = scanner()->peek_location().beg_pos;
    106   PreParserStatementList body;
    107   ParseStatementList(body, Token::EOS, &ok);
    108   original_scope_ = nullptr;
    109   if (stack_overflow()) return kPreParseStackOverflow;
    110   if (!ok) {
    111     ReportUnexpectedToken(scanner()->current_token());
    112   } else if (is_strict(language_mode())) {
    113     CheckStrictOctalLiteral(start_position, scanner()->location().end_pos, &ok);
    114   }
    115   return kPreParseSuccess;
    116 }
    117 
    118 PreParser::PreParseResult PreParser::PreParseFunction(
    119     const AstRawString* function_name, FunctionKind kind,
    120     FunctionLiteral::FunctionType function_type,
    121     DeclarationScope* function_scope, bool is_inner_function, bool may_abort,
    122     int* use_counts, ProducedPreParsedScopeData** produced_preparsed_scope_data,
    123     int script_id) {
    124   DCHECK_EQ(FUNCTION_SCOPE, function_scope->scope_type());
    125   use_counts_ = use_counts;
    126   DCHECK(!track_unresolved_variables_);
    127   track_unresolved_variables_ = is_inner_function;
    128   set_script_id(script_id);
    129 #ifdef DEBUG
    130   function_scope->set_is_being_lazily_parsed(true);
    131 #endif
    132 
    133   // Start collecting data for a new function which might contain skippable
    134   // functions.
    135   std::unique_ptr<ProducedPreParsedScopeData::DataGatheringScope>
    136       produced_preparsed_scope_data_scope;
    137   if (FLAG_preparser_scope_analysis && !IsArrowFunction(kind)) {
    138     track_unresolved_variables_ = true;
    139     produced_preparsed_scope_data_scope.reset(
    140         new ProducedPreParsedScopeData::DataGatheringScope(function_scope,
    141                                                            this));
    142   }
    143 
    144   // In the preparser, we use the function literal ids to count how many
    145   // FunctionLiterals were encountered. The PreParser doesn't actually persist
    146   // FunctionLiterals, so there IDs don't matter.
    147   ResetFunctionLiteralId();
    148 
    149   // The caller passes the function_scope which is not yet inserted into the
    150   // scope stack. All scopes above the function_scope are ignored by the
    151   // PreParser.
    152   DCHECK_NULL(function_state_);
    153   DCHECK_NULL(scope_);
    154   FunctionState function_state(&function_state_, &scope_, function_scope);
    155   // This indirection is needed so that we can use the CHECK_OK macros.
    156   bool ok_holder = true;
    157   bool* ok = &ok_holder;
    158 
    159   PreParserFormalParameters formals(function_scope);
    160   DuplicateFinder duplicate_finder;
    161   std::unique_ptr<ExpressionClassifier> formals_classifier;
    162 
    163   // Parse non-arrow function parameters. For arrow functions, the parameters
    164   // have already been parsed.
    165   if (!IsArrowFunction(kind)) {
    166     formals_classifier.reset(new ExpressionClassifier(this, &duplicate_finder));
    167     // We return kPreParseSuccess in failure cases too - errors are retrieved
    168     // separately by Parser::SkipLazyFunctionBody.
    169     ParseFormalParameterList(&formals, CHECK_OK_VALUE(kPreParseSuccess));
    170     Expect(Token::RPAREN, CHECK_OK_VALUE(kPreParseSuccess));
    171     int formals_end_position = scanner()->location().end_pos;
    172 
    173     CheckArityRestrictions(
    174         formals.arity, kind, formals.has_rest, function_scope->start_position(),
    175         formals_end_position, CHECK_OK_VALUE(kPreParseSuccess));
    176   }
    177 
    178   Expect(Token::LBRACE, CHECK_OK_VALUE(kPreParseSuccess));
    179   DeclarationScope* inner_scope = function_scope;
    180   LazyParsingResult result;
    181 
    182   if (!formals.is_simple) {
    183     inner_scope = NewVarblockScope();
    184     inner_scope->set_start_position(scanner()->location().beg_pos);
    185   }
    186 
    187   {
    188     BlockState block_state(&scope_, inner_scope);
    189     result = ParseStatementListAndLogFunction(&formals, may_abort, ok);
    190   }
    191 
    192   if (!formals.is_simple) {
    193     BuildParameterInitializationBlock(formals, ok);
    194 
    195     if (is_sloppy(inner_scope->language_mode())) {
    196       inner_scope->HoistSloppyBlockFunctions(nullptr);
    197     }
    198 
    199     SetLanguageMode(function_scope, inner_scope->language_mode());
    200     inner_scope->set_end_position(scanner()->peek_location().end_pos);
    201     inner_scope->FinalizeBlockScope();
    202   } else {
    203     if (is_sloppy(function_scope->language_mode())) {
    204       function_scope->HoistSloppyBlockFunctions(nullptr);
    205     }
    206   }
    207 
    208   if (!IsArrowFunction(kind) && track_unresolved_variables_ &&
    209       result == kLazyParsingComplete) {
    210     // Declare arguments after parsing the function since lexical 'arguments'
    211     // masks the arguments object. Declare arguments before declaring the
    212     // function var since the arguments object masks 'function arguments'.
    213     function_scope->DeclareArguments(ast_value_factory());
    214 
    215     DeclareFunctionNameVar(function_name, function_type, function_scope);
    216   }
    217 
    218   use_counts_ = nullptr;
    219   track_unresolved_variables_ = false;
    220 
    221   if (result == kLazyParsingAborted) {
    222     return kPreParseAbort;
    223   } else if (stack_overflow()) {
    224     return kPreParseStackOverflow;
    225   } else if (!*ok) {
    226     DCHECK(pending_error_handler()->has_pending_error());
    227   } else {
    228     DCHECK_EQ(Token::RBRACE, scanner()->peek());
    229 
    230     if (!IsArrowFunction(kind)) {
    231       // Validate parameter names. We can do this only after parsing the
    232       // function, since the function can declare itself strict.
    233       const bool allow_duplicate_parameters =
    234           is_sloppy(function_scope->language_mode()) && formals.is_simple &&
    235           !IsConciseMethod(kind);
    236       ValidateFormalParameters(function_scope->language_mode(),
    237                                allow_duplicate_parameters,
    238                                CHECK_OK_VALUE(kPreParseSuccess));
    239 
    240       *produced_preparsed_scope_data = produced_preparsed_scope_data_;
    241     }
    242 
    243     if (is_strict(function_scope->language_mode())) {
    244       int end_pos = scanner()->location().end_pos;
    245       CheckStrictOctalLiteral(function_scope->start_position(), end_pos, ok);
    246     }
    247   }
    248   return kPreParseSuccess;
    249 }
    250 
    251 
    252 // Preparsing checks a JavaScript program and emits preparse-data that helps
    253 // a later parsing to be faster.
    254 // See preparser-data.h for the data.
    255 
    256 // The PreParser checks that the syntax follows the grammar for JavaScript,
    257 // and collects some information about the program along the way.
    258 // The grammar check is only performed in order to understand the program
    259 // sufficiently to deduce some information about it, that can be used
    260 // to speed up later parsing. Finding errors is not the goal of pre-parsing,
    261 // rather it is to speed up properly written and correct programs.
    262 // That means that contextual checks (like a label being declared where
    263 // it is used) are generally omitted.
    264 
    265 PreParser::Expression PreParser::ParseFunctionLiteral(
    266     Identifier function_name, Scanner::Location function_name_location,
    267     FunctionNameValidity function_name_validity, FunctionKind kind,
    268     int function_token_pos, FunctionLiteral::FunctionType function_type,
    269     LanguageMode language_mode,
    270     ZonePtrList<const AstRawString>* arguments_for_wrapped_function, bool* ok) {
    271   // Wrapped functions are not parsed in the preparser.
    272   DCHECK_NULL(arguments_for_wrapped_function);
    273   DCHECK_NE(FunctionLiteral::kWrapped, function_type);
    274   // Function ::
    275   //   '(' FormalParameterList? ')' '{' FunctionBody '}'
    276   const RuntimeCallCounterId counters[2][2] = {
    277       {RuntimeCallCounterId::kPreParseBackgroundNoVariableResolution,
    278        RuntimeCallCounterId::kPreParseNoVariableResolution},
    279       {RuntimeCallCounterId::kPreParseBackgroundWithVariableResolution,
    280        RuntimeCallCounterId::kPreParseWithVariableResolution}};
    281   RuntimeCallTimerScope runtime_timer(
    282       runtime_call_stats_,
    283       counters[track_unresolved_variables_][parsing_on_main_thread_]);
    284 
    285   base::ElapsedTimer timer;
    286   if (V8_UNLIKELY(FLAG_log_function_events)) timer.Start();
    287 
    288   DeclarationScope* function_scope = NewFunctionScope(kind);
    289   function_scope->SetLanguageMode(language_mode);
    290 
    291   // Start collecting data for a new function which might contain skippable
    292   // functions.
    293   std::unique_ptr<ProducedPreParsedScopeData::DataGatheringScope>
    294       produced_preparsed_scope_data_scope;
    295   if (!function_state_->next_function_is_likely_called() &&
    296       produced_preparsed_scope_data_ != nullptr) {
    297     DCHECK(FLAG_preparser_scope_analysis);
    298     DCHECK(track_unresolved_variables_);
    299     produced_preparsed_scope_data_scope.reset(
    300         new ProducedPreParsedScopeData::DataGatheringScope(function_scope,
    301                                                            this));
    302   }
    303 
    304   FunctionState function_state(&function_state_, &scope_, function_scope);
    305   DuplicateFinder duplicate_finder;
    306   ExpressionClassifier formals_classifier(this, &duplicate_finder);
    307   int func_id = GetNextFunctionLiteralId();
    308 
    309   Expect(Token::LPAREN, CHECK_OK);
    310   int start_position = scanner()->location().beg_pos;
    311   function_scope->set_start_position(start_position);
    312   PreParserFormalParameters formals(function_scope);
    313   ParseFormalParameterList(&formals, CHECK_OK);
    314   Expect(Token::RPAREN, CHECK_OK);
    315   int formals_end_position = scanner()->location().end_pos;
    316 
    317   CheckArityRestrictions(formals.arity, kind, formals.has_rest, start_position,
    318                          formals_end_position, CHECK_OK);
    319 
    320   Expect(Token::LBRACE, CHECK_OK);
    321 
    322   // Parse function body.
    323   PreParserStatementList body;
    324   int pos = function_token_pos == kNoSourcePosition ? peek_position()
    325                                                     : function_token_pos;
    326   ParseFunctionBody(body, function_name, pos, formals, kind, function_type,
    327                     CHECK_OK);
    328 
    329   // Parsing the body may change the language mode in our scope.
    330   language_mode = function_scope->language_mode();
    331 
    332   if (is_sloppy(language_mode)) {
    333     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                     function_name_location, CHECK_OK);
    340   const bool allow_duplicate_parameters =
    341       is_sloppy(language_mode) && formals.is_simple && !IsConciseMethod(kind);
    342   ValidateFormalParameters(language_mode, allow_duplicate_parameters, CHECK_OK);
    343 
    344   int end_position = scanner()->location().end_pos;
    345   if (is_strict(language_mode)) {
    346     CheckStrictOctalLiteral(start_position, end_position, CHECK_OK);
    347   }
    348 
    349   if (produced_preparsed_scope_data_scope) {
    350     produced_preparsed_scope_data_scope->MarkFunctionAsSkippable(
    351         end_position, GetLastFunctionLiteralId() - func_id);
    352   }
    353   if (V8_UNLIKELY(FLAG_log_function_events)) {
    354     double ms = timer.Elapsed().InMillisecondsF();
    355     const char* event_name = track_unresolved_variables_
    356                                  ? "preparse-resolution"
    357                                  : "preparse-no-resolution";
    358     // We might not always get a function name here. However, it can be easily
    359     // reconstructed from the script id and the byte range in the log processor.
    360     const char* name = "";
    361     size_t name_byte_length = 0;
    362     const AstRawString* string = function_name.string_;
    363     if (string != nullptr) {
    364       name = reinterpret_cast<const char*>(string->raw_data());
    365       name_byte_length = string->byte_length();
    366     }
    367     logger_->FunctionEvent(
    368         event_name, script_id(), ms, function_scope->start_position(),
    369         function_scope->end_position(), name, name_byte_length);
    370   }
    371 
    372   return Expression::Default();
    373 }
    374 
    375 PreParser::LazyParsingResult PreParser::ParseStatementListAndLogFunction(
    376     PreParserFormalParameters* formals, bool may_abort, bool* ok) {
    377   PreParserStatementList body;
    378   LazyParsingResult result = ParseStatementList(
    379       body, Token::RBRACE, may_abort, CHECK_OK_VALUE(kLazyParsingComplete));
    380   if (result == kLazyParsingAborted) return result;
    381 
    382   // Position right after terminal '}'.
    383   DCHECK_EQ(Token::RBRACE, scanner()->peek());
    384   int body_end = scanner()->peek_location().end_pos;
    385   DCHECK_EQ(this->scope()->is_function_scope(), formals->is_simple);
    386   log_.LogFunction(body_end, formals->num_parameters(),
    387                    GetLastFunctionLiteralId());
    388   return kLazyParsingComplete;
    389 }
    390 
    391 PreParserStatement PreParser::BuildParameterInitializationBlock(
    392     const PreParserFormalParameters& parameters, bool* ok) {
    393   DCHECK(!parameters.is_simple);
    394   DCHECK(scope()->is_function_scope());
    395   if (FLAG_preparser_scope_analysis &&
    396       scope()->AsDeclarationScope()->calls_sloppy_eval() &&
    397       produced_preparsed_scope_data_ != nullptr) {
    398     // We cannot replicate the Scope structure constructed by the Parser,
    399     // because we've lost information whether each individual parameter was
    400     // simple or not. Give up trying to produce data to skip inner functions.
    401     if (produced_preparsed_scope_data_->parent() != nullptr) {
    402       // Lazy parsing started before the current function; the function which
    403       // cannot contain skippable functions is the parent function. (Its inner
    404       // functions cannot either; they are implicitly bailed out.)
    405       produced_preparsed_scope_data_->parent()->Bailout();
    406     } else {
    407       // Lazy parsing started at the current function; it cannot contain
    408       // skippable functions.
    409       produced_preparsed_scope_data_->Bailout();
    410     }
    411   }
    412 
    413   return PreParserStatement::Default();
    414 }
    415 
    416 PreParserExpression PreParser::ExpressionFromIdentifier(
    417     const PreParserIdentifier& name, int start_position, InferName infer) {
    418   VariableProxy* proxy = nullptr;
    419   if (track_unresolved_variables_) {
    420     DCHECK_NOT_NULL(name.string_);
    421     proxy = scope()->NewUnresolved(factory()->ast_node_factory(), name.string_,
    422                                    start_position, NORMAL_VARIABLE);
    423   }
    424   return PreParserExpression::FromIdentifier(name, proxy, zone());
    425 }
    426 
    427 void PreParser::DeclareAndInitializeVariables(
    428     PreParserStatement block,
    429     const DeclarationDescriptor* declaration_descriptor,
    430     const DeclarationParsingResult::Declaration* declaration,
    431     ZonePtrList<const AstRawString>* names, bool* ok) {
    432   if (declaration->pattern.variables_ != nullptr) {
    433     DCHECK(FLAG_lazy_inner_functions);
    434     DCHECK(track_unresolved_variables_);
    435     for (auto variable : *(declaration->pattern.variables_)) {
    436       declaration_descriptor->scope->RemoveUnresolved(variable);
    437       Variable* var = scope()->DeclareVariableName(
    438           variable->raw_name(), declaration_descriptor->mode);
    439       if (FLAG_preparser_scope_analysis) {
    440         MarkLoopVariableAsAssigned(declaration_descriptor->scope, var,
    441                                    declaration_descriptor->declaration_kind);
    442         // This is only necessary if there is an initializer, but we don't have
    443         // that information here.  Consequently, the preparser sometimes says
    444         // maybe-assigned where the parser (correctly) says never-assigned.
    445       }
    446       if (names) {
    447         names->Add(variable->raw_name(), zone());
    448       }
    449     }
    450   }
    451 }
    452 
    453 #undef CHECK_OK
    454 #undef CHECK_OK_CUSTOM
    455 
    456 
    457 }  // namespace internal
    458 }  // namespace v8
    459