preparser.cc 15.3 KB
Newer Older
1
// Copyright 2011 the V8 project authors. All rights reserved.
2 3
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
4

5
#include <cmath>
6

7
#include "src/base/logging.h"
8
#include "src/common/globals.h"
9 10
#include "src/numbers/conversions-inl.h"
#include "src/numbers/conversions.h"
11
#include "src/parsing/parser-base.h"
12
#include "src/parsing/preparse-data.h"
13
#include "src/parsing/preparser.h"
14
#include "src/strings/unicode.h"
15 16
#include "src/utils/allocation.h"
#include "src/utils/utils.h"
17
#include "src/zone/zone-list-inl.h"
18

19
namespace v8 {
20
namespace internal {
21

22 23
namespace {

24 25 26
PreParserIdentifier GetIdentifierHelper(Scanner* scanner,
                                        const AstRawString* string,
                                        AstValueFactory* avf) {
27
  // These symbols require slightly different treatement:
28
  // - regular keywords (async, await, etc.; treated in 1st switch.)
29 30
  // - 'contextual' keywords (and may contain escaped; treated in 2nd switch.)
  // - 'contextual' keywords, but may not be escaped (3rd switch).
31
  switch (scanner->current_token()) {
32 33 34 35
    case Token::AWAIT:
      return PreParserIdentifier::Await();
    case Token::ASYNC:
      return PreParserIdentifier::Async();
36 37
    case Token::PRIVATE_NAME:
      return PreParserIdentifier::PrivateName();
38
    default:
39
      break;
40
  }
41 42 43 44 45
  if (string == avf->constructor_string()) {
    return PreParserIdentifier::Constructor();
  }
  if (string == avf->name_string()) {
    return PreParserIdentifier::Name();
46
  }
47
  if (scanner->literal_contains_escapes()) {
48
    return PreParserIdentifier::Default();
49
  }
50 51 52 53 54
  if (string == avf->eval_string()) {
    return PreParserIdentifier::Eval();
  }
  if (string == avf->arguments_string()) {
    return PreParserIdentifier::Arguments();
55 56
  }
  return PreParserIdentifier::Default();
57 58
}

59 60
}  // unnamed namespace

61
PreParserIdentifier PreParser::GetIdentifier() const {
62
  const AstRawString* result = scanner()->CurrentSymbol(ast_value_factory());
63
  PreParserIdentifier symbol =
64
      GetIdentifierHelper(scanner(), result, ast_value_factory());
65 66
  DCHECK_NOT_NULL(result);
  symbol.string_ = result;
67 68 69
  return symbol;
}

70
PreParser::PreParseResult PreParser::PreParseProgram() {
71 72 73 74 75 76
  DCHECK_NULL(scope_);
  DeclarationScope* scope = NewScriptScope();
#ifdef DEBUG
  scope->set_is_being_lazily_parsed(true);
#endif

77 78 79 80 81 82
  if (FLAG_harmony_hashbang) {
    // Note: We should only skip the hashbang in non-Eval scripts
    // (currently, Eval is not handled by the PreParser).
    scanner()->SkipHashBang();
  }

83 84 85
  // ModuleDeclarationInstantiation for Source Text Module Records creates a
  // new Module Environment Record whose outer lexical environment record is
  // the global scope.
86
  if (parsing_module_) scope = NewModuleScope(scope);
87 88 89

  FunctionState top_scope(&function_state_, &scope_, scope);
  original_scope_ = scope_;
90
  int start_position = peek_position();
91 92
  PreParserScopedStatementList body(pointer_buffer());
  ParseStatementList(&body, Token::EOS);
93
  CheckConflictingVarDeclarations(scope);
94 95
  original_scope_ = nullptr;
  if (stack_overflow()) return kPreParseStackOverflow;
96
  if (is_strict(language_mode())) {
97
    CheckStrictOctalLiteral(start_position, scanner()->location().end_pos);
98 99 100 101
  }
  return kPreParseSuccess;
}

102 103 104 105 106 107 108 109
void PreParserFormalParameters::ValidateDuplicate(PreParser* preparser) const {
  if (has_duplicate_) preparser->ReportUnidentifiableError();
}

void PreParserFormalParameters::ValidateStrictMode(PreParser* preparser) const {
  if (strict_parameter_error_) preparser->ReportUnidentifiableError();
}

110
PreParser::PreParseResult PreParser::PreParseFunction(
111 112
    const AstRawString* function_name, FunctionKind kind,
    FunctionLiteral::FunctionType function_type,
113
    DeclarationScope* function_scope, int* use_counts,
114
    ProducedPreparseData** produced_preparse_data, int script_id) {
115
  DCHECK_EQ(FUNCTION_SCOPE, function_scope->scope_type());
116
  use_counts_ = use_counts;
117
  set_script_id(script_id);
118 119 120
#ifdef DEBUG
  function_scope->set_is_being_lazily_parsed(true);
#endif
121

122
  PreParserFormalParameters formals(function_scope);
123

124 125 126 127 128
  // In the preparser, we use the function literal ids to count how many
  // FunctionLiterals were encountered. The PreParser doesn't actually persist
  // FunctionLiterals, so there IDs don't matter.
  ResetFunctionLiteralId();

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 133 134
  DCHECK_NULL(function_state_);
  DCHECK_NULL(scope_);
  FunctionState function_state(&function_state_, &scope_, function_scope);
135

136 137
  // Start collecting data for a new function which might contain skippable
  // functions.
138
  PreparseDataBuilder::DataGatheringScope preparse_data_builder_scope(this);
139

140 141 142
  if (IsArrowFunction(kind)) {
    formals.is_simple = function_scope->has_simple_parameters();
  } else {
143
    preparse_data_builder_scope.Start(function_scope);
144 145 146

    // Parse non-arrow function parameters. For arrow functions, the parameters
    // have already been parsed.
147
    ParameterDeclarationParsingScope formals_scope(this);
148 149
    // We return kPreParseSuccess in failure cases too - errors are retrieved
    // separately by Parser::SkipLazyFunctionBody.
150
    ParseFormalParameterList(&formals);
151
    if (formals_scope.has_duplicate()) formals.set_has_duplicate();
152 153 154 155
    if (!formals.is_simple) {
      BuildParameterInitializationBlock(formals);
    }

156
    Expect(Token::RPAREN);
157 158
    int formals_end_position = scanner()->location().end_pos;

159 160 161
    CheckArityRestrictions(formals.arity, kind, formals.has_rest,
                           function_scope->start_position(),
                           formals_end_position);
162 163
  }

164
  Expect(Token::LBRACE);
165 166 167 168
  DeclarationScope* inner_scope = function_scope;

  if (!formals.is_simple) {
    inner_scope = NewVarblockScope();
169
    inner_scope->set_start_position(position());
170 171 172
  }

  {
173
    BlockState block_state(&scope_, inner_scope);
174
    ParseStatementListAndLogFunction(&formals);
175 176
  }

177
  bool allow_duplicate_parameters = false;
178
  CheckConflictingVarDeclarations(inner_scope);
179

180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200
  if (!has_error()) {
    if (formals.is_simple) {
      if (is_sloppy(function_scope->language_mode())) {
        function_scope->HoistSloppyBlockFunctions(nullptr);
      }

      allow_duplicate_parameters =
          is_sloppy(function_scope->language_mode()) && !IsConciseMethod(kind);
    } else {
      if (is_sloppy(inner_scope->language_mode())) {
        inner_scope->HoistSloppyBlockFunctions(nullptr);
      }

      SetLanguageMode(function_scope, inner_scope->language_mode());
      inner_scope->set_end_position(scanner()->peek_location().end_pos);
      if (inner_scope->FinalizeBlockScope() != nullptr) {
        const AstRawString* conflict = inner_scope->FindVariableDeclaredIn(
            function_scope, VariableMode::kLastLexicalVariableMode);
        if (conflict != nullptr)
          ReportVarRedeclarationIn(conflict, inner_scope);
      }
201
    }
202 203
  }

204
  use_counts_ = nullptr;
205

206
  if (stack_overflow()) {
207
    return kPreParseStackOverflow;
208
  } else if (pending_error_handler()->has_error_unidentifiable_by_preparser()) {
209
    return kPreParseNotIdentifiableError;
210
  } else if (has_error()) {
211
    DCHECK(pending_error_handler()->has_pending_error());
212
  } else {
213
    DCHECK_EQ(Token::RBRACE, scanner()->peek());
214 215 216 217

    if (!IsArrowFunction(kind)) {
      // Validate parameter names. We can do this only after parsing the
      // function, since the function can declare itself strict.
218 219
      ValidateFormalParameters(language_mode(), formals,
                               allow_duplicate_parameters);
220
      if (has_error()) {
221
        if (pending_error_handler()->has_error_unidentifiable_by_preparser()) {
222 223 224 225 226 227
          return kPreParseNotIdentifiableError;
        } else {
          return kPreParseSuccess;
        }
      }

228 229 230 231 232
      // Declare arguments after parsing the function since lexical
      // 'arguments' masks the arguments object. Declare arguments before
      // declaring the function var since the arguments object masks 'function
      // arguments'.
      function_scope->DeclareArguments(ast_value_factory());
233

234
      DeclareFunctionNameVar(function_name, function_type, function_scope);
235

236 237 238 239
      if (preparse_data_builder_->HasData()) {
        *produced_preparse_data =
            ProducedPreparseData::For(preparse_data_builder_, main_zone());
      }
240
    }
241 242 243 244

    if (pending_error_handler()->has_error_unidentifiable_by_preparser()) {
      return kPreParseNotIdentifiableError;
    }
245

246
    if (is_strict(function_scope->language_mode())) {
247
      int end_pos = scanner()->location().end_pos;
248
      CheckStrictOctalLiteral(function_scope->start_position(), end_pos);
249 250
    }
  }
251

252
  DCHECK(!pending_error_handler()->has_error_unidentifiable_by_preparser());
253 254 255
  return kPreParseSuccess;
}

256 257 258 259 260 261 262 263 264 265 266 267 268
// Preparsing checks a JavaScript program and emits preparse-data that helps
// a later parsing to be faster.
// See preparser-data.h for the data.

// The PreParser checks that the syntax follows the grammar for JavaScript,
// and collects some information about the program along the way.
// The grammar check is only performed in order to understand the program
// sufficiently to deduce some information about it, that can be used
// to speed up later parsing. Finding errors is not the goal of pre-parsing,
// rather it is to speed up properly written and correct programs.
// That means that contextual checks (like a label being declared where
// it is used) are generally omitted.

269
PreParser::Expression PreParser::ParseFunctionLiteral(
270
    Identifier function_name, Scanner::Location function_name_location,
271 272
    FunctionNameValidity function_name_validity, FunctionKind kind,
    int function_token_pos, FunctionLiteral::FunctionType function_type,
273
    LanguageMode language_mode,
274
    ZonePtrList<const AstRawString>* arguments_for_wrapped_function) {
275 276 277
  // Wrapped functions are not parsed in the preparser.
  DCHECK_NULL(arguments_for_wrapped_function);
  DCHECK_NE(FunctionLiteral::kWrapped, function_type);
278 279
  // Function ::
  //   '(' FormalParameterList? ')' '{' FunctionBody '}'
280 281 282 283 284
  const RuntimeCallCounterId counters[2] = {
      RuntimeCallCounterId::kPreParseBackgroundWithVariableResolution,
      RuntimeCallCounterId::kPreParseWithVariableResolution};
  RuntimeCallTimerScope runtime_timer(runtime_call_stats_,
                                      counters[parsing_on_main_thread_]);
285

286 287 288
  base::ElapsedTimer timer;
  if (V8_UNLIKELY(FLAG_log_function_events)) timer.Start();

289
  DeclarationScope* function_scope = NewFunctionScope(kind);
290
  function_scope->SetLanguageMode(language_mode);
291 292
  int func_id = GetNextFunctionLiteralId();
  bool skippable_function = false;
293 294 295

  // Start collecting data for a new function which might contain skippable
  // functions.
296
  {
297
    PreparseDataBuilder::DataGatheringScope preparse_data_builder_scope(this);
298
    skippable_function = !function_state_->next_function_is_likely_called() &&
299
                         preparse_data_builder_ != nullptr;
300
    if (skippable_function) {
301
      preparse_data_builder_scope.Start(function_scope);
302
    }
303

304
    FunctionState function_state(&function_state_, &scope_, function_scope);
305

306 307 308 309
    Expect(Token::LPAREN);
    int start_position = position();
    function_scope->set_start_position(start_position);
    PreParserFormalParameters formals(function_scope);
310
    {
311
      ParameterDeclarationParsingScope formals_scope(this);
312
      ParseFormalParameterList(&formals);
313
      if (formals_scope.has_duplicate()) formals.set_has_duplicate();
314
    }
315 316
    Expect(Token::RPAREN);
    int formals_end_position = scanner()->location().end_pos;
317

318 319
    CheckArityRestrictions(formals.arity, kind, formals.has_rest,
                           start_position, formals_end_position);
320

321
    Expect(Token::LBRACE);
322

323 324 325 326 327 328 329
    // Parse function body.
    PreParserScopedStatementList body(pointer_buffer());
    int pos = function_token_pos == kNoSourcePosition ? peek_position()
                                                      : function_token_pos;
    AcceptINScope scope(this, true);
    ParseFunctionBody(&body, function_name, pos, formals, kind, function_type,
                      FunctionBodyType::kBlock);
330

331 332
    // Parsing the body may change the language mode in our scope.
    language_mode = function_scope->language_mode();
333

334 335 336
    if (is_sloppy(language_mode)) {
      function_scope->HoistSloppyBlockFunctions(nullptr);
    }
337

338 339 340 341
    // Validate name and parameter names. We can do this only after parsing the
    // function, since the function can declare itself strict.
    CheckFunctionName(language_mode, function_name, function_name_validity,
                      function_name_location);
342

343 344 345
    if (is_strict(language_mode)) {
      CheckStrictOctalLiteral(start_position, end_position());
    }
346
    if (skippable_function) {
347
      preparse_data_builder_scope.SetSkippableFunction(
348 349
          function_scope, formals.function_length,
          GetLastFunctionLiteralId() - func_id);
350
    }
351
  }
352

353 354
  if (V8_UNLIKELY(FLAG_log_function_events)) {
    double ms = timer.Elapsed().InMillisecondsF();
355
    const char* event_name = "preparse-resolution";
356 357 358 359 360 361 362 363 364 365
    // We might not always get a function name here. However, it can be easily
    // reconstructed from the script id and the byte range in the log processor.
    const char* name = "";
    size_t name_byte_length = 0;
    const AstRawString* string = function_name.string_;
    if (string != nullptr) {
      name = reinterpret_cast<const char*>(string->raw_data());
      name_byte_length = string->byte_length();
    }
    logger_->FunctionEvent(
366
        event_name, script_id(), ms, function_scope->start_position(),
367
        function_scope->end_position(), name, name_byte_length);
368
  }
369

370
  return Expression::Default();
371 372
}

373 374
void PreParser::ParseStatementListAndLogFunction(
    PreParserFormalParameters* formals) {
375
  PreParserScopedStatementList body(pointer_buffer());
376
  ParseStatementList(&body, Token::RBRACE);
377 378

  // Position right after terminal '}'.
379
  DCHECK_IMPLIES(!has_error(), scanner()->peek() == Token::RBRACE);
380
  int body_end = scanner()->peek_location().end_pos;
381
  DCHECK_EQ(this->scope()->is_function_scope(), formals->is_simple);
382
  log_.LogFunction(body_end, formals->num_parameters(),
383
                   formals->function_length, GetLastFunctionLiteralId());
384 385
}

386
PreParserBlock PreParser::BuildParameterInitializationBlock(
387
    const PreParserFormalParameters& parameters) {
388
  DCHECK(!parameters.is_simple);
389
  DCHECK(scope()->is_function_scope());
390
  if (scope()->AsDeclarationScope()->calls_sloppy_eval() &&
391
      preparse_data_builder_ != nullptr) {
392 393 394
    // We cannot replicate the Scope structure constructed by the Parser,
    // because we've lost information whether each individual parameter was
    // simple or not. Give up trying to produce data to skip inner functions.
395
    if (preparse_data_builder_->parent() != nullptr) {
396 397 398
      // Lazy parsing started before the current function; the function which
      // cannot contain skippable functions is the parent function. (Its inner
      // functions cannot either; they are implicitly bailed out.)
399
      preparse_data_builder_->parent()->Bailout();
400 401 402
    } else {
      // Lazy parsing started at the current function; it cannot contain
      // skippable functions.
403
      preparse_data_builder_->Bailout();
404 405 406
    }
  }

407
  return PreParserBlock::Default();
408 409
}

410 411 412 413 414
bool PreParser::IdentifierEquals(const PreParserIdentifier& identifier,
                                 const AstRawString* other) {
  return identifier.string_ == other;
}

415 416
}  // namespace internal
}  // namespace v8