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 : #include "src/zone/zone-list-inl.h"
18 :
19 : namespace v8 {
20 : namespace internal {
21 :
22 : namespace {
23 :
24 41436567 : PreParserIdentifier GetIdentifierHelper(Scanner* scanner,
25 : const AstRawString* string,
26 : AstValueFactory* avf) {
27 : // These symbols require slightly different treatement:
28 : // - regular keywords (async, await, etc.; treated in 1st switch.)
29 : // - 'contextual' keywords (and may contain escaped; treated in 2nd switch.)
30 : // - 'contextual' keywords, but may not be escaped (3rd switch).
31 41436567 : switch (scanner->current_token()) {
32 : case Token::AWAIT:
33 : return PreParserIdentifier::Await();
34 : case Token::ASYNC:
35 : return PreParserIdentifier::Async();
36 : case Token::PRIVATE_NAME:
37 : return PreParserIdentifier::PrivateName();
38 : default:
39 : break;
40 : }
41 41368632 : if (string == avf->constructor_string()) {
42 : return PreParserIdentifier::Constructor();
43 : }
44 41364133 : if (string == avf->name_string()) {
45 : return PreParserIdentifier::Name();
46 : }
47 40771394 : if (scanner->literal_contains_escapes()) {
48 : return PreParserIdentifier::Default();
49 : }
50 40768700 : if (string == avf->eval_string()) {
51 : return PreParserIdentifier::Eval();
52 : }
53 40671023 : if (string == avf->arguments_string()) {
54 : return PreParserIdentifier::Arguments();
55 : }
56 : return PreParserIdentifier::Default();
57 : }
58 :
59 : } // unnamed namespace
60 :
61 41431787 : PreParserIdentifier PreParser::GetIdentifier() const {
62 41431787 : const AstRawString* result = scanner()->CurrentSymbol(ast_value_factory());
63 : PreParserIdentifier symbol =
64 41436113 : GetIdentifierHelper(scanner(), result, ast_value_factory());
65 : DCHECK_NOT_NULL(result);
66 : symbol.string_ = result;
67 41436192 : return symbol;
68 : }
69 :
70 523079 : PreParser::PreParseResult PreParser::PreParseProgram() {
71 : DCHECK_NULL(scope_);
72 523079 : DeclarationScope* scope = NewScriptScope();
73 : #ifdef DEBUG
74 : scope->set_is_being_lazily_parsed(true);
75 : #endif
76 :
77 523079 : if (FLAG_harmony_hashbang) {
78 : // Note: We should only skip the hashbang in non-Eval scripts
79 : // (currently, Eval is not handled by the PreParser).
80 513359 : scanner()->SkipHashBang();
81 : }
82 :
83 : // ModuleDeclarationInstantiation for Source Text Module Records creates a
84 : // new Module Environment Record whose outer lexical environment record is
85 : // the global scope.
86 523079 : if (parsing_module_) scope = NewModuleScope(scope);
87 :
88 523079 : FunctionState top_scope(&function_state_, &scope_, scope);
89 523079 : original_scope_ = scope_;
90 : int start_position = peek_position();
91 : PreParserScopedStatementList body(pointer_buffer());
92 : ParseStatementList(&body, Token::EOS);
93 523079 : CheckConflictingVarDeclarations(scope);
94 523079 : original_scope_ = nullptr;
95 523079 : if (stack_overflow()) return kPreParseStackOverflow;
96 523074 : if (is_strict(language_mode())) {
97 138020 : CheckStrictOctalLiteral(start_position, scanner()->location().end_pos);
98 : }
99 : return kPreParseSuccess;
100 : }
101 :
102 1020594 : void PreParserFormalParameters::ValidateDuplicate(PreParser* preparser) const {
103 1020594 : if (has_duplicate_) preparser->ReportUnidentifiableError();
104 1020594 : }
105 :
106 908228 : void PreParserFormalParameters::ValidateStrictMode(PreParser* preparser) const {
107 908228 : if (strict_parameter_error_) preparser->ReportUnidentifiableError();
108 908228 : }
109 :
110 2542575 : PreParser::PreParseResult PreParser::PreParseFunction(
111 : const AstRawString* function_name, FunctionKind kind,
112 : 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 2542575 : use_counts_ = use_counts;
117 : set_script_id(script_id);
118 : #ifdef DEBUG
119 : function_scope->set_is_being_lazily_parsed(true);
120 : #endif
121 :
122 : PreParserFormalParameters formals(function_scope);
123 :
124 : // In the preparser, we use the function literal ids to count how many
125 : // FunctionLiterals were encountered. The PreParser doesn't actually persist
126 : // FunctionLiterals, so there IDs don't matter.
127 : ResetFunctionLiteralId();
128 :
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 : DCHECK_NULL(function_state_);
133 : DCHECK_NULL(scope_);
134 2542575 : FunctionState function_state(&function_state_, &scope_, function_scope);
135 :
136 : // Start collecting data for a new function which might contain skippable
137 : // functions.
138 : PreparseDataBuilder::DataGatheringScope preparse_data_builder_scope(this);
139 :
140 2542575 : if (IsArrowFunction(kind)) {
141 30239 : formals.is_simple = function_scope->has_simple_parameters();
142 : } else {
143 2512336 : preparse_data_builder_scope.Start(function_scope);
144 :
145 : // Parse non-arrow function parameters. For arrow functions, the parameters
146 : // have already been parsed.
147 : ParameterDeclarationParsingScope formals_scope(this);
148 : // We return kPreParseSuccess in failure cases too - errors are retrieved
149 : // separately by Parser::SkipLazyFunctionBody.
150 2512320 : ParseFormalParameterList(&formals);
151 2512308 : if (formals_scope.has_duplicate()) formals.set_has_duplicate();
152 2512308 : if (!formals.is_simple) {
153 105549 : BuildParameterInitializationBlock(formals);
154 : }
155 :
156 2512306 : Expect(Token::RPAREN);
157 2512331 : int formals_end_position = scanner()->location().end_pos;
158 :
159 2512331 : CheckArityRestrictions(formals.arity, kind, formals.has_rest,
160 : function_scope->start_position(),
161 2512331 : formals_end_position);
162 : }
163 :
164 2542556 : Expect(Token::LBRACE);
165 : DeclarationScope* inner_scope = function_scope;
166 :
167 2542568 : if (!formals.is_simple) {
168 111799 : inner_scope = NewVarblockScope();
169 : inner_scope->set_start_position(position());
170 : }
171 :
172 : {
173 : BlockState block_state(&scope_, inner_scope);
174 2542572 : ParseStatementListAndLogFunction(&formals);
175 : }
176 :
177 : bool allow_duplicate_parameters = false;
178 2542546 : CheckConflictingVarDeclarations(inner_scope);
179 :
180 2542568 : if (!has_error()) {
181 2484135 : if (formals.is_simple) {
182 2385685 : if (is_sloppy(function_scope->language_mode())) {
183 1916921 : function_scope->HoistSloppyBlockFunctions(nullptr);
184 : }
185 :
186 : allow_duplicate_parameters =
187 4302602 : is_sloppy(function_scope->language_mode()) && !IsConciseMethod(kind);
188 : } else {
189 98450 : if (is_sloppy(inner_scope->language_mode())) {
190 76646 : inner_scope->HoistSloppyBlockFunctions(nullptr);
191 : }
192 :
193 : SetLanguageMode(function_scope, inner_scope->language_mode());
194 98449 : inner_scope->set_end_position(scanner()->peek_location().end_pos);
195 98449 : if (inner_scope->FinalizeBlockScope() != nullptr) {
196 : const AstRawString* conflict = inner_scope->FindVariableDeclaredIn(
197 75076 : function_scope, VariableMode::kLastLexicalVariableMode);
198 75077 : if (conflict != nullptr)
199 : ReportVarRedeclarationIn(conflict, inner_scope);
200 : }
201 : }
202 : }
203 :
204 2542579 : use_counts_ = nullptr;
205 :
206 2542579 : if (stack_overflow()) {
207 : return kPreParseStackOverflow;
208 2542533 : } else if (pending_error_handler()->has_error_unidentifiable_by_preparser()) {
209 : return kPreParseNotIdentifiableError;
210 2495129 : } else if (has_error()) {
211 : DCHECK(pending_error_handler()->has_pending_error());
212 : } else {
213 : DCHECK_EQ(Token::RBRACE, scanner()->peek());
214 :
215 2484112 : if (!IsArrowFunction(kind)) {
216 : // Validate parameter names. We can do this only after parsing the
217 : // function, since the function can declare itself strict.
218 2459921 : ValidateFormalParameters(language_mode(), formals,
219 2459921 : allow_duplicate_parameters);
220 2459924 : if (has_error()) {
221 1465 : if (pending_error_handler()->has_error_unidentifiable_by_preparser()) {
222 : return kPreParseNotIdentifiableError;
223 : } else {
224 0 : return kPreParseSuccess;
225 : }
226 : }
227 :
228 : // Declare arguments after parsing the function since lexical
229 : // 'arguments' masks the arguments object. Declare arguments before
230 : // declaring the function var since the arguments object masks 'function
231 : // arguments'.
232 2458459 : function_scope->DeclareArguments(ast_value_factory());
233 :
234 : DeclareFunctionNameVar(function_name, function_type, function_scope);
235 :
236 2458454 : if (preparse_data_builder_->HasData()) {
237 : *produced_preparse_data =
238 84418 : ProducedPreparseData::For(preparse_data_builder_, main_zone());
239 : }
240 : }
241 :
242 2482641 : if (pending_error_handler()->has_error_unidentifiable_by_preparser()) {
243 : return kPreParseNotIdentifiableError;
244 : }
245 :
246 2482645 : if (is_strict(function_scope->language_mode())) {
247 489482 : int end_pos = scanner()->location().end_pos;
248 489482 : CheckStrictOctalLiteral(function_scope->start_position(), end_pos);
249 : }
250 : }
251 :
252 : DCHECK(!pending_error_handler()->has_error_unidentifiable_by_preparser());
253 : return kPreParseSuccess;
254 : }
255 :
256 : // Preparsing checks a JavaScript program and emits preparse-data that helps
257 : // a later parsing to be faster.
258 : // See preparser-data.h for the data.
259 :
260 : // The PreParser checks that the syntax follows the grammar for JavaScript,
261 : // and collects some information about the program along the way.
262 : // The grammar check is only performed in order to understand the program
263 : // sufficiently to deduce some information about it, that can be used
264 : // to speed up later parsing. Finding errors is not the goal of pre-parsing,
265 : // rather it is to speed up properly written and correct programs.
266 : // That means that contextual checks (like a label being declared where
267 : // it is used) are generally omitted.
268 :
269 424196 : PreParser::Expression PreParser::ParseFunctionLiteral(
270 : Identifier function_name, Scanner::Location function_name_location,
271 : FunctionNameValidity function_name_validity, FunctionKind kind,
272 : int function_token_pos, FunctionLiteral::FunctionType function_type,
273 : LanguageMode language_mode,
274 : ZonePtrList<const AstRawString>* arguments_for_wrapped_function) {
275 : // Wrapped functions are not parsed in the preparser.
276 : DCHECK_NULL(arguments_for_wrapped_function);
277 : DCHECK_NE(FunctionLiteral::kWrapped, function_type);
278 : // Function ::
279 : // '(' FormalParameterList? ')' '{' FunctionBody '}'
280 : const RuntimeCallCounterId counters[2] = {
281 : RuntimeCallCounterId::kPreParseBackgroundWithVariableResolution,
282 424196 : RuntimeCallCounterId::kPreParseWithVariableResolution};
283 : RuntimeCallTimerScope runtime_timer(runtime_call_stats_,
284 424196 : counters[parsing_on_main_thread_]);
285 :
286 : base::ElapsedTimer timer;
287 424196 : if (V8_UNLIKELY(FLAG_log_function_events)) timer.Start();
288 :
289 424196 : DeclarationScope* function_scope = NewFunctionScope(kind);
290 : function_scope->SetLanguageMode(language_mode);
291 : int func_id = GetNextFunctionLiteralId();
292 : bool skippable_function = false;
293 :
294 : // Start collecting data for a new function which might contain skippable
295 : // functions.
296 : {
297 : PreparseDataBuilder::DataGatheringScope preparse_data_builder_scope(this);
298 811689 : skippable_function = !function_state_->next_function_is_likely_called() &&
299 387491 : preparse_data_builder_ != nullptr;
300 424198 : if (skippable_function) {
301 147982 : preparse_data_builder_scope.Start(function_scope);
302 : }
303 :
304 424197 : FunctionState function_state(&function_state_, &scope_, function_scope);
305 :
306 424197 : Expect(Token::LPAREN);
307 : int start_position = position();
308 : function_scope->set_start_position(start_position);
309 : PreParserFormalParameters formals(function_scope);
310 : {
311 : ParameterDeclarationParsingScope formals_scope(this);
312 424198 : ParseFormalParameterList(&formals);
313 424197 : if (formals_scope.has_duplicate()) formals.set_has_duplicate();
314 : }
315 424197 : Expect(Token::RPAREN);
316 424197 : int formals_end_position = scanner()->location().end_pos;
317 :
318 424197 : CheckArityRestrictions(formals.arity, kind, formals.has_rest,
319 424197 : start_position, formals_end_position);
320 :
321 424196 : Expect(Token::LBRACE);
322 :
323 : // Parse function body.
324 : PreParserScopedStatementList body(pointer_buffer());
325 : int pos = function_token_pos == kNoSourcePosition ? peek_position()
326 424196 : : function_token_pos;
327 : AcceptINScope scope(this, true);
328 : ParseFunctionBody(&body, function_name, pos, formals, kind, function_type,
329 424196 : FunctionBodyType::kBlock);
330 :
331 : // Parsing the body may change the language mode in our scope.
332 : language_mode = function_scope->language_mode();
333 :
334 424195 : if (is_sloppy(language_mode)) {
335 213565 : function_scope->HoistSloppyBlockFunctions(nullptr);
336 : }
337 :
338 : // Validate name and parameter names. We can do this only after parsing the
339 : // function, since the function can declare itself strict.
340 : CheckFunctionName(language_mode, function_name, function_name_validity,
341 424196 : function_name_location);
342 :
343 424195 : if (is_strict(language_mode)) {
344 210630 : CheckStrictOctalLiteral(start_position, end_position());
345 : }
346 424195 : if (skippable_function) {
347 147980 : preparse_data_builder_scope.SetSkippableFunction(
348 147980 : function_scope, GetLastFunctionLiteralId() - func_id);
349 : }
350 : }
351 :
352 424196 : if (V8_UNLIKELY(FLAG_log_function_events)) {
353 9 : double ms = timer.Elapsed().InMillisecondsF();
354 : const char* event_name = "preparse-resolution";
355 : // We might not always get a function name here. However, it can be easily
356 : // reconstructed from the script id and the byte range in the log processor.
357 : const char* name = "";
358 : size_t name_byte_length = 0;
359 9 : const AstRawString* string = function_name.string_;
360 9 : if (string != nullptr) {
361 : name = reinterpret_cast<const char*>(string->raw_data());
362 3 : name_byte_length = string->byte_length();
363 : }
364 9 : logger_->FunctionEvent(
365 : event_name, script_id(), ms, function_scope->start_position(),
366 9 : function_scope->end_position(), name, name_byte_length);
367 : }
368 :
369 424196 : return Expression::Default();
370 : }
371 :
372 2542545 : void PreParser::ParseStatementListAndLogFunction(
373 : PreParserFormalParameters* formals) {
374 : PreParserScopedStatementList body(pointer_buffer());
375 2542545 : ParseStatementList(&body, Token::RBRACE);
376 :
377 : // Position right after terminal '}'.
378 : DCHECK_IMPLIES(!has_error(), scanner()->peek() == Token::RBRACE);
379 2542527 : int body_end = scanner()->peek_location().end_pos;
380 : DCHECK_EQ(this->scope()->is_function_scope(), formals->is_simple);
381 : log_.LogFunction(body_end, formals->num_parameters(),
382 : GetLastFunctionLiteralId());
383 2542527 : }
384 :
385 127203 : PreParserBlock PreParser::BuildParameterInitializationBlock(
386 : const PreParserFormalParameters& parameters) {
387 : DCHECK(!parameters.is_simple);
388 : DCHECK(scope()->is_function_scope());
389 254992 : if (scope()->AsDeclarationScope()->calls_sloppy_eval() &&
390 587 : preparse_data_builder_ != nullptr) {
391 : // We cannot replicate the Scope structure constructed by the Parser,
392 : // because we've lost information whether each individual parameter was
393 : // simple or not. Give up trying to produce data to skip inner functions.
394 581 : if (preparse_data_builder_->parent() != nullptr) {
395 : // Lazy parsing started before the current function; the function which
396 : // cannot contain skippable functions is the parent function. (Its inner
397 : // functions cannot either; they are implicitly bailed out.)
398 : preparse_data_builder_->parent()->Bailout();
399 : } else {
400 : // Lazy parsing started at the current function; it cannot contain
401 : // skippable functions.
402 : preparse_data_builder_->Bailout();
403 : }
404 : }
405 :
406 127202 : return PreParserBlock::Default();
407 : }
408 :
409 0 : bool PreParser::IdentifierEquals(const PreParserIdentifier& identifier,
410 : const AstRawString* other) {
411 0 : return identifier.string_ == other;
412 : }
413 :
414 : } // namespace internal
415 120216 : } // namespace v8
|