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/list.h"
13 : #include "src/parsing/duplicate-finder.h"
14 : #include "src/parsing/parser-base.h"
15 : #include "src/parsing/preparse-data-format.h"
16 : #include "src/parsing/preparse-data.h"
17 : #include "src/parsing/preparsed-scope-data.h"
18 : #include "src/parsing/preparser.h"
19 : #include "src/unicode.h"
20 : #include "src/utils.h"
21 :
22 : namespace v8 {
23 : namespace internal {
24 :
25 : // ----------------------------------------------------------------------------
26 : // The CHECK_OK macro is a convenient macro to enforce error
27 : // handling for functions that may fail (by returning !*ok).
28 : //
29 : // CAUTION: This macro appends extra statements after a call,
30 : // thus it must never be used where only a single statement
31 : // is correct (e.g. an if statement branch w/o braces)!
32 :
33 : #define CHECK_OK_VALUE(x) ok); \
34 : if (!*ok) return x; \
35 : ((void)0
36 : #define DUMMY ) // to make indentation work
37 : #undef DUMMY
38 :
39 : #define CHECK_OK CHECK_OK_VALUE(Expression::Default())
40 : #define CHECK_OK_VOID CHECK_OK_VALUE(this->Void())
41 :
42 : namespace {
43 :
44 66206535 : PreParserIdentifier GetSymbolHelper(Scanner* scanner) {
45 : // These symbols require slightly different treatement:
46 : // - regular keywords (enum, await, etc.; treated in 1st switch.)
47 : // - 'contextual' keywords (and may contain escaped; treated in 2nd switch.)
48 : // - 'contextual' keywords, but may not be escaped (3rd switch).
49 33144495 : switch (scanner->current_token()) {
50 : case Token::ENUM:
51 : return PreParserIdentifier::Enum();
52 : case Token::AWAIT:
53 : return PreParserIdentifier::Await();
54 : case Token::FUTURE_STRICT_RESERVED_WORD:
55 : return PreParserIdentifier::FutureStrictReserved();
56 : case Token::LET:
57 : return PreParserIdentifier::Let();
58 : case Token::STATIC:
59 : return PreParserIdentifier::Static();
60 : case Token::YIELD:
61 : return PreParserIdentifier::Yield();
62 : case Token::ASYNC:
63 : return PreParserIdentifier::Async();
64 : default:
65 : break;
66 : }
67 33062040 : switch (scanner->current_contextual_token()) {
68 : case Token::PROTOTYPE:
69 : return PreParserIdentifier::Prototype();
70 : case Token::CONSTRUCTOR:
71 : return PreParserIdentifier::Constructor();
72 : case Token::NAME:
73 : return PreParserIdentifier::Name();
74 : default:
75 : break;
76 : }
77 32730672 : if (scanner->literal_contains_escapes())
78 : return PreParserIdentifier::Default();
79 32727074 : switch (scanner->current_contextual_token()) {
80 : case Token::EVAL:
81 : return PreParserIdentifier::Eval();
82 : case Token::ARGUMENTS:
83 : return PreParserIdentifier::Arguments();
84 : case Token::UNDEFINED:
85 : return PreParserIdentifier::Undefined();
86 : default:
87 : break;
88 : }
89 : return PreParserIdentifier::Default();
90 : }
91 :
92 : } // unnamed namespace
93 :
94 33144495 : PreParserIdentifier PreParser::GetSymbol() const {
95 43910640 : PreParserIdentifier symbol = GetSymbolHelper(scanner());
96 33144494 : if (track_unresolved_variables_) {
97 10766145 : const AstRawString* result = scanner()->CurrentSymbol(ast_value_factory());
98 : DCHECK_NOT_NULL(result);
99 : symbol.string_ = result;
100 : }
101 33144494 : return symbol;
102 : }
103 :
104 480923 : PreParser::PreParseResult PreParser::PreParseProgram(bool is_module,
105 : int* use_counts) {
106 : DCHECK_NULL(scope_);
107 480923 : use_counts_ = use_counts;
108 1724005 : DeclarationScope* scope = NewScriptScope();
109 : #ifdef DEBUG
110 : scope->set_is_being_lazily_parsed(true);
111 : #endif
112 :
113 : // ModuleDeclarationInstantiation for Source Text Module Records creates a
114 : // new Module Environment Record whose outer lexical environment record is
115 : // the global scope.
116 480923 : if (is_module) scope = NewModuleScope(scope);
117 :
118 480923 : FunctionState top_scope(&function_state_, &scope_, scope);
119 480923 : original_scope_ = scope_;
120 480923 : bool ok = true;
121 : int start_position = scanner()->peek_location().beg_pos;
122 480923 : parsing_module_ = is_module;
123 : PreParserStatementList body;
124 : ParseStatementList(body, Token::EOS, &ok);
125 480923 : original_scope_ = nullptr;
126 480923 : use_counts_ = nullptr;
127 480923 : if (stack_overflow()) return kPreParseStackOverflow;
128 480917 : if (!ok) {
129 215596 : ReportUnexpectedToken(scanner()->current_token());
130 265321 : } else if (is_strict(language_mode())) {
131 65640 : CheckStrictOctalLiteral(start_position, scanner()->location().end_pos, &ok);
132 : }
133 : return kPreParseSuccess;
134 : }
135 :
136 1434068 : PreParser::PreParseResult PreParser::PreParseFunction(
137 : FunctionKind kind, DeclarationScope* function_scope, bool parsing_module,
138 : bool is_inner_function, bool may_abort, int* use_counts) {
139 : DCHECK_EQ(FUNCTION_SCOPE, function_scope->scope_type());
140 1434068 : parsing_module_ = parsing_module;
141 1434068 : use_counts_ = use_counts;
142 : DCHECK(!track_unresolved_variables_);
143 1434068 : track_unresolved_variables_ = is_inner_function;
144 : #ifdef DEBUG
145 : function_scope->set_is_being_lazily_parsed(true);
146 : #endif
147 :
148 : // In the preparser, we use the function literal ids to count how many
149 : // FunctionLiterals were encountered. The PreParser doesn't actually persist
150 : // FunctionLiterals, so there IDs don't matter.
151 3726226 : ResetFunctionLiteralId();
152 :
153 : // The caller passes the function_scope which is not yet inserted into the
154 : // scope stack. All scopes above the function_scope are ignored by the
155 : // PreParser.
156 : DCHECK_NULL(function_state_);
157 : DCHECK_NULL(scope_);
158 1434068 : FunctionState function_state(&function_state_, &scope_, function_scope);
159 : // This indirection is needed so that we can use the CHECK_OK macros.
160 1434068 : bool ok_holder = true;
161 : bool* ok = &ok_holder;
162 :
163 : PreParserFormalParameters formals(function_scope);
164 : DuplicateFinder duplicate_finder;
165 : std::unique_ptr<ExpressionClassifier> formals_classifier;
166 :
167 : // Parse non-arrow function parameters. For arrow functions, the parameters
168 : // have already been parsed.
169 1434068 : if (!IsArrowFunction(kind)) {
170 1402868 : formals_classifier.reset(new ExpressionClassifier(this, &duplicate_finder));
171 : // We return kPreParseSuccess in failure cases too - errors are retrieved
172 : // separately by Parser::SkipLazyFunctionBody.
173 1402869 : ParseFormalParameterList(&formals, CHECK_OK_VALUE(kPreParseSuccess));
174 1392318 : Expect(Token::RPAREN, CHECK_OK_VALUE(kPreParseSuccess));
175 : int formals_end_position = scanner()->location().end_pos;
176 :
177 : CheckArityRestrictions(
178 : formals.arity, kind, formals.has_rest, function_scope->start_position(),
179 1666116 : formals_end_position, CHECK_OK_VALUE(kPreParseSuccess));
180 : }
181 :
182 1422385 : Expect(Token::LBRACE, CHECK_OK_VALUE(kPreParseSuccess));
183 : DeclarationScope* inner_scope = function_scope;
184 : LazyParsingResult result;
185 :
186 1422338 : if (!formals.is_simple) {
187 15606 : inner_scope = NewVarblockScope();
188 : inner_scope->set_start_position(scanner()->location().beg_pos);
189 : }
190 :
191 : {
192 : BlockState block_state(&scope_, inner_scope);
193 1422338 : result = ParseStatementListAndLogFunction(&formals, may_abort, ok);
194 : }
195 :
196 1422338 : if (!formals.is_simple) {
197 : BuildParameterInitializationBlock(formals, ok);
198 :
199 15606 : if (is_sloppy(inner_scope->language_mode())) {
200 12449 : inner_scope->HoistSloppyBlockFunctions(nullptr);
201 : }
202 :
203 : SetLanguageMode(function_scope, inner_scope->language_mode());
204 : inner_scope->set_end_position(scanner()->peek_location().end_pos);
205 15606 : inner_scope->FinalizeBlockScope();
206 : } else {
207 1406732 : if (is_sloppy(function_scope->language_mode())) {
208 1112089 : function_scope->HoistSloppyBlockFunctions(nullptr);
209 : }
210 : }
211 :
212 1422338 : if (!IsArrowFunction(kind) && track_unresolved_variables_) {
213 : // Declare arguments after parsing the function since lexical 'arguments'
214 : // masks the arguments object. Declare arguments before declaring the
215 : // function var since the arguments object masks 'function arguments'.
216 532607 : function_scope->DeclareArguments(ast_value_factory());
217 :
218 547408 : if (FLAG_experimental_preparser_scope_analysis &&
219 14801 : preparsed_scope_data_ != nullptr) {
220 : // We're not going to skip this function, but it might contain skippable
221 : // functions inside it.
222 : preparsed_scope_data_->AddFunction(
223 : scope()->start_position(),
224 : PreParseData::FunctionData(
225 : scanner()->peek_location().end_pos, scope()->num_parameters(),
226 : GetLastFunctionLiteralId(), scope()->language_mode(),
227 44403 : scope()->AsDeclarationScope()->uses_super_property()));
228 : }
229 : }
230 :
231 1422338 : use_counts_ = nullptr;
232 1422338 : track_unresolved_variables_ = false;
233 :
234 1422338 : if (result == kLazyParsingAborted) {
235 : return kPreParseAbort;
236 1422286 : } else if (stack_overflow()) {
237 : return kPreParseStackOverflow;
238 1422234 : } else if (!*ok) {
239 : DCHECK(pending_error_handler_->has_pending_error());
240 : } else {
241 : DCHECK_EQ(Token::RBRACE, scanner()->peek());
242 :
243 1386477 : if (!IsArrowFunction(kind)) {
244 : // Validate parameter names. We can do this only after parsing the
245 : // function, since the function can declare itself strict.
246 : const bool allow_duplicate_parameters =
247 2428345 : is_sloppy(function_scope->language_mode()) && formals.is_simple &&
248 : !IsConciseMethod(kind);
249 : ValidateFormalParameters(function_scope->language_mode(),
250 : allow_duplicate_parameters,
251 2715696 : CHECK_OK_VALUE(kPreParseSuccess));
252 : }
253 :
254 1384339 : if (is_strict(function_scope->language_mode())) {
255 : int end_pos = scanner()->location().end_pos;
256 274619 : CheckStrictOctalLiteral(function_scope->start_position(), end_pos, ok);
257 : }
258 : }
259 : return kPreParseSuccess;
260 : }
261 :
262 :
263 : // Preparsing checks a JavaScript program and emits preparse-data that helps
264 : // a later parsing to be faster.
265 : // See preparser-data.h for the data.
266 :
267 : // The PreParser checks that the syntax follows the grammar for JavaScript,
268 : // and collects some information about the program along the way.
269 : // The grammar check is only performed in order to understand the program
270 : // sufficiently to deduce some information about it, that can be used
271 : // to speed up later parsing. Finding errors is not the goal of pre-parsing,
272 : // rather it is to speed up properly written and correct programs.
273 : // That means that contextual checks (like a label being declared where
274 : // it is used) are generally omitted.
275 :
276 385764 : PreParser::Expression PreParser::ParseFunctionLiteral(
277 : Identifier function_name, Scanner::Location function_name_location,
278 : FunctionNameValidity function_name_validity, FunctionKind kind,
279 : int function_token_pos, FunctionLiteral::FunctionType function_type,
280 : LanguageMode language_mode, bool* ok) {
281 : // Function ::
282 : // '(' FormalParameterList? ')' '{' FunctionBody '}'
283 : const RuntimeCallStats::CounterId counters[2][2] = {
284 : {&RuntimeCallStats::PreParseBackgroundNoVariableResolution,
285 : &RuntimeCallStats::PreParseNoVariableResolution},
286 : {&RuntimeCallStats::PreParseBackgroundWithVariableResolution,
287 385764 : &RuntimeCallStats::PreParseWithVariableResolution}};
288 : RuntimeCallTimerScope runtime_timer(
289 : runtime_call_stats_,
290 385764 : counters[track_unresolved_variables_][parsing_on_main_thread_]);
291 :
292 : bool is_top_level =
293 1503977 : scope()->AllowsLazyParsingWithoutUnresolvedVariables(original_scope_);
294 :
295 385764 : DeclarationScope* function_scope = NewFunctionScope(kind);
296 0 : function_scope->SetLanguageMode(language_mode);
297 385764 : FunctionState function_state(&function_state_, &scope_, function_scope);
298 : DuplicateFinder duplicate_finder;
299 385764 : ExpressionClassifier formals_classifier(this, &duplicate_finder);
300 : int func_id = GetNextFunctionLiteralId();
301 :
302 385764 : Expect(Token::LPAREN, CHECK_OK);
303 : int start_position = scanner()->location().beg_pos;
304 : function_scope->set_start_position(start_position);
305 : PreParserFormalParameters formals(function_scope);
306 382552 : ParseFormalParameterList(&formals, CHECK_OK);
307 359428 : Expect(Token::RPAREN, CHECK_OK);
308 : int formals_end_position = scanner()->location().end_pos;
309 :
310 : CheckArityRestrictions(formals.arity, kind, formals.has_rest, start_position,
311 357830 : formals_end_position, CHECK_OK);
312 :
313 356633 : Expect(Token::LBRACE, CHECK_OK);
314 :
315 : // Parse function body.
316 : PreParserStatementList body;
317 : int pos = function_token_pos == kNoSourcePosition ? peek_position()
318 356297 : : function_token_pos;
319 : ParseFunctionBody(body, function_name, pos, formals, kind, function_type,
320 356297 : CHECK_OK);
321 :
322 : // Parsing the body may change the language mode in our scope.
323 : language_mode = function_scope->language_mode();
324 :
325 293966 : if (is_sloppy(language_mode)) {
326 199393 : function_scope->HoistSloppyBlockFunctions(nullptr);
327 : }
328 :
329 : // Validate name and parameter names. We can do this only after parsing the
330 : // function, since the function can declare itself strict.
331 : CheckFunctionName(language_mode, function_name, function_name_validity,
332 293966 : function_name_location, CHECK_OK);
333 : const bool allow_duplicate_parameters =
334 479324 : is_sloppy(language_mode) && formals.is_simple && !IsConciseMethod(kind);
335 292062 : ValidateFormalParameters(language_mode, allow_duplicate_parameters, CHECK_OK);
336 :
337 : int end_position = scanner()->location().end_pos;
338 289311 : if (is_strict(language_mode)) {
339 91019 : CheckStrictOctalLiteral(start_position, end_position, CHECK_OK);
340 : }
341 :
342 289230 : if (FLAG_use_parse_tasks && is_top_level && preparse_data_) {
343 : preparse_data_->AddFunctionData(
344 : start_position, PreParseData::FunctionData(
345 : end_position, formals.num_parameters(),
346 : GetLastFunctionLiteralId() - func_id, language_mode,
347 0 : function_scope->uses_super_property()));
348 : // TODO(wiktorg) spin-off a parse task
349 0 : if (FLAG_trace_parse_tasks) {
350 : PrintF("Saved function at %d to %d with:\n", start_position,
351 0 : end_position);
352 0 : PrintF("\t- %d params\n", formals.num_parameters());
353 0 : PrintF("\t- %d function length\n", formals.function_length);
354 0 : PrintF("\t- %d inner-funcs\n", GetLastFunctionLiteralId() - func_id);
355 : }
356 : }
357 :
358 289230 : if (FLAG_experimental_preparser_scope_analysis &&
359 10656 : track_unresolved_variables_ && preparsed_scope_data_ != nullptr) {
360 : preparsed_scope_data_->AddSkippableFunction(
361 : start_position,
362 : PreParseData::FunctionData(
363 : end_position, scope()->num_parameters(),
364 : GetLastFunctionLiteralId() - func_id, scope()->language_mode(),
365 31968 : scope()->AsDeclarationScope()->uses_super_property()));
366 : }
367 289230 : if (FLAG_trace_preparse) {
368 : PrintF(" [%s]: %i-%i\n",
369 : track_unresolved_variables_ ? "Preparse resolution"
370 : : "Preparse no-resolution",
371 0 : function_scope->start_position(), function_scope->end_position());
372 : }
373 :
374 : return Expression::Default();
375 : }
376 :
377 1422338 : PreParser::LazyParsingResult PreParser::ParseStatementListAndLogFunction(
378 : PreParserFormalParameters* formals, bool may_abort, bool* ok) {
379 : PreParserStatementList body;
380 : LazyParsingResult result = ParseStatementList(
381 2808815 : body, Token::RBRACE, may_abort, CHECK_OK_VALUE(kLazyParsingComplete));
382 1386529 : if (result == kLazyParsingAborted) return result;
383 :
384 : // Position right after terminal '}'.
385 : DCHECK_EQ(Token::RBRACE, scanner()->peek());
386 : int body_end = scanner()->peek_location().end_pos;
387 : DCHECK_EQ(this->scope()->is_function_scope(), formals->is_simple);
388 : log_.LogFunction(body_end, formals->num_parameters(),
389 1386477 : GetLastFunctionLiteralId());
390 1386477 : return kLazyParsingComplete;
391 : }
392 :
393 28362984 : PreParserExpression PreParser::ExpressionFromIdentifier(
394 28362984 : PreParserIdentifier name, int start_position, InferName infer) {
395 : VariableProxy* proxy = nullptr;
396 28362984 : if (track_unresolved_variables_) {
397 55736367 : AstNodeFactory factory(ast_value_factory());
398 : // Setting the Zone is necessary because zone_ might be the temp Zone, and
399 : // AstValueFactory doesn't know about it.
400 : factory.set_zone(zone());
401 : DCHECK_NOT_NULL(name.string_);
402 : proxy = scope()->NewUnresolved(&factory, name.string_, start_position,
403 18248922 : NORMAL_VARIABLE);
404 : }
405 28362984 : return PreParserExpression::FromIdentifier(name, proxy, zone());
406 : }
407 :
408 4405135 : void PreParser::DeclareAndInitializeVariables(
409 : PreParserStatement block,
410 : const DeclarationDescriptor* declaration_descriptor,
411 : const DeclarationParsingResult::Declaration* declaration,
412 : ZoneList<const AstRawString*>* names, bool* ok) {
413 4405135 : if (declaration->pattern.variables_ != nullptr) {
414 : DCHECK(FLAG_lazy_inner_functions);
415 : DCHECK(track_unresolved_variables_);
416 2203134 : for (auto variable : *(declaration->pattern.variables_)) {
417 736460 : declaration_descriptor->scope->RemoveUnresolved(variable);
418 : Variable* var = scope()->DeclareVariableName(
419 1484094 : variable->raw_name(), declaration_descriptor->mode);
420 736460 : if (FLAG_experimental_preparser_scope_analysis) {
421 11783 : MarkLoopVariableAsAssigned(declaration_descriptor->scope, var);
422 : // This is only necessary if there is an initializer, but we don't have
423 : // that information here. Consequently, the preparser sometimes says
424 : // maybe-assigned where the parser (correctly) says never-assigned.
425 : }
426 736460 : if (names) {
427 : names->Add(variable->raw_name(), zone());
428 : }
429 : }
430 : }
431 4405135 : }
432 :
433 : #undef CHECK_OK
434 : #undef CHECK_OK_CUSTOM
435 :
436 :
437 : } // namespace internal
438 : } // namespace v8
|