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
|