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