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 51498785 : PreParserIdentifier GetSymbolHelper(Scanner* scanner,
25 : const AstRawString* string,
26 51431011 : 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 51498785 : 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 51431011 : if (string == avf->constructor_string()) {
42 : return PreParserIdentifier::Constructor();
43 : }
44 51367165 : if (string == avf->name_string()) {
45 : return PreParserIdentifier::Name();
46 : }
47 50461248 : if (scanner->literal_contains_escapes()) {
48 : return PreParserIdentifier::Default();
49 : }
50 50457764 : if (string == avf->eval_string()) {
51 : return PreParserIdentifier::Eval();
52 : }
53 50359528 : if (string == avf->arguments_string()) {
54 : return PreParserIdentifier::Arguments();
55 : }
56 : return PreParserIdentifier::Default();
57 : }
58 :
59 : } // unnamed namespace
60 :
61 51473448 : PreParserIdentifier PreParser::GetSymbol() const {
62 51473448 : const AstRawString* result = scanner()->CurrentSymbol(ast_value_factory());
63 : PreParserIdentifier symbol =
64 51496982 : GetSymbolHelper(scanner(), result, ast_value_factory());
65 : DCHECK_NOT_NULL(result);
66 : symbol.string_ = result;
67 51496831 : return symbol;
68 : }
69 :
70 520319 : PreParser::PreParseResult PreParser::PreParseProgram() {
71 : DCHECK_NULL(scope_);
72 1188378 : DeclarationScope* scope = NewScriptScope();
73 : #ifdef DEBUG
74 : scope->set_is_being_lazily_parsed(true);
75 : #endif
76 :
77 520319 : 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 9720 : 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 520319 : if (parsing_module_) scope = NewModuleScope(scope);
87 :
88 520319 : FunctionState top_scope(&function_state_, &scope_, scope);
89 520319 : original_scope_ = scope_;
90 : int start_position = peek_position();
91 : PreParserScopedStatementList body(pointer_buffer());
92 : ParseStatementList(&body, Token::EOS);
93 520319 : CheckConflictingVarDeclarations(scope);
94 520319 : original_scope_ = nullptr;
95 520319 : if (stack_overflow()) return kPreParseStackOverflow;
96 520314 : if (is_strict(language_mode())) {
97 138020 : CheckStrictOctalLiteral(start_position, scanner()->location().end_pos);
98 : }
99 : return kPreParseSuccess;
100 : }
101 :
102 1000347 : void PreParserFormalParameters::ValidateDuplicate(PreParser* preparser) const {
103 1000347 : if (has_duplicate_) preparser->ReportUnidentifiableError();
104 1000346 : }
105 :
106 887425 : void PreParserFormalParameters::ValidateStrictMode(PreParser* preparser) const {
107 887425 : if (strict_parameter_error_) preparser->ReportUnidentifiableError();
108 887425 : }
109 :
110 2510039 : PreParser::PreParseResult PreParser::PreParseFunction(
111 : const AstRawString* function_name, FunctionKind kind,
112 : FunctionLiteral::FunctionType function_type,
113 : DeclarationScope* function_scope, int* use_counts,
114 2452519 : ProducedPreparseData** produced_preparse_data, int script_id) {
115 : DCHECK_EQ(FUNCTION_SCOPE, function_scope->scope_type());
116 2510039 : use_counts_ = use_counts;
117 5591756 : 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 2510039 : 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 2510039 : if (IsArrowFunction(kind)) {
141 30180 : formals.is_simple = function_scope->has_simple_parameters();
142 : } else {
143 2479859 : 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 2479773 : ParseFormalParameterList(&formals);
151 2479775 : if (formals_scope.has_duplicate()) formals.set_has_duplicate();
152 2479775 : if (!formals.is_simple) {
153 106794 : BuildParameterInitializationBlock(formals);
154 : }
155 :
156 2479775 : Expect(Token::RPAREN);
157 2479897 : int formals_end_position = scanner()->location().end_pos;
158 :
159 : CheckArityRestrictions(formals.arity, kind, formals.has_rest,
160 : function_scope->start_position(),
161 2952218 : formals_end_position);
162 : }
163 :
164 2510047 : Expect(Token::LBRACE);
165 : DeclarationScope* inner_scope = function_scope;
166 :
167 2510136 : if (!formals.is_simple) {
168 112981 : inner_scope = NewVarblockScope();
169 : inner_scope->set_start_position(position());
170 : }
171 :
172 : {
173 : BlockState block_state(&scope_, inner_scope);
174 2510144 : ParseStatementListAndLogFunction(&formals);
175 : }
176 :
177 : bool allow_duplicate_parameters = false;
178 2510066 : CheckConflictingVarDeclarations(inner_scope);
179 :
180 2510068 : if (!has_error()) {
181 2452477 : if (formals.is_simple) {
182 2352785 : if (is_sloppy(function_scope->language_mode())) {
183 1901865 : function_scope->HoistSloppyBlockFunctions(nullptr);
184 : }
185 :
186 : allow_duplicate_parameters =
187 4254499 : is_sloppy(function_scope->language_mode()) && !IsConciseMethod(kind);
188 : } else {
189 99692 : if (is_sloppy(inner_scope->language_mode())) {
190 77205 : inner_scope->HoistSloppyBlockFunctions(nullptr);
191 : }
192 :
193 : SetLanguageMode(function_scope, inner_scope->language_mode());
194 99699 : inner_scope->set_end_position(scanner()->peek_location().end_pos);
195 99699 : if (inner_scope->FinalizeBlockScope() != nullptr) {
196 : const AstRawString* conflict = inner_scope->FindVariableDeclaredIn(
197 76970 : function_scope, VariableMode::kLastLexicalVariableMode);
198 76975 : if (conflict != nullptr)
199 : ReportVarRedeclarationIn(conflict, inner_scope);
200 : }
201 : }
202 : }
203 :
204 2510029 : use_counts_ = nullptr;
205 :
206 2510029 : if (stack_overflow()) {
207 : return kPreParseStackOverflow;
208 2510060 : } else if (pending_error_handler()->has_error_unidentifiable_by_preparser()) {
209 : return kPreParseNotIdentifiableError;
210 2463453 : } else if (has_error()) {
211 : DCHECK(pending_error_handler()->has_pending_error());
212 : } else {
213 : DCHECK_EQ(Token::RBRACE, scanner()->peek());
214 :
215 2452483 : 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 : ValidateFormalParameters(language_mode(), formals,
219 4856506 : allow_duplicate_parameters);
220 2428315 : 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 2426850 : function_scope->DeclareArguments(ast_value_factory());
233 :
234 : DeclareFunctionNameVar(function_name, function_type, function_scope);
235 :
236 2426850 : if (preparse_data_builder_->HasData()) {
237 : *produced_preparse_data =
238 84106 : ProducedPreparseData::For(preparse_data_builder_, main_zone());
239 : }
240 : }
241 :
242 2451054 : if (pending_error_handler()->has_error_unidentifiable_by_preparser()) {
243 : return kPreParseNotIdentifiableError;
244 : }
245 :
246 2451036 : if (is_strict(function_scope->language_mode())) {
247 472321 : int end_pos = scanner()->location().end_pos;
248 472321 : 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 421637 : PreParser::Expression PreParser::ParseFunctionLiteral(
270 421667 : 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 421637 : RuntimeCallCounterId::kPreParseWithVariableResolution};
283 : RuntimeCallTimerScope runtime_timer(runtime_call_stats_,
284 421637 : counters[parsing_on_main_thread_]);
285 :
286 : base::ElapsedTimer timer;
287 421641 : if (V8_UNLIKELY(FLAG_log_function_events)) timer.Start();
288 :
289 1621359 : DeclarationScope* function_scope = NewFunctionScope(kind);
290 9 : 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 806652 : skippable_function = !function_state_->next_function_is_likely_called() &&
299 384978 : preparse_data_builder_ != nullptr;
300 421674 : if (skippable_function) {
301 146892 : preparse_data_builder_scope.Start(function_scope);
302 : }
303 :
304 421673 : FunctionState function_state(&function_state_, &scope_, function_scope);
305 :
306 421673 : 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 421679 : ParseFormalParameterList(&formals);
313 421678 : if (formals_scope.has_duplicate()) formals.set_has_duplicate();
314 : }
315 421678 : Expect(Token::RPAREN);
316 421674 : int formals_end_position = scanner()->location().end_pos;
317 :
318 : CheckArityRestrictions(formals.arity, kind, formals.has_rest,
319 421674 : start_position, formals_end_position);
320 :
321 421674 : Expect(Token::LBRACE);
322 :
323 : // Parse function body.
324 : PreParserScopedStatementList body(pointer_buffer());
325 : int pos = function_token_pos == kNoSourcePosition ? peek_position()
326 421675 : : function_token_pos;
327 : AcceptINScope scope(this, true);
328 : ParseFunctionBody(&body, function_name, pos, formals, kind, function_type,
329 421675 : FunctionBodyType::kBlock);
330 :
331 : // Parsing the body may change the language mode in our scope.
332 : language_mode = function_scope->language_mode();
333 :
334 421667 : if (is_sloppy(language_mode)) {
335 212193 : 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 421667 : function_name_location);
342 :
343 421658 : if (is_strict(language_mode)) {
344 209480 : CheckStrictOctalLiteral(start_position, end_position());
345 : }
346 421668 : if (skippable_function) {
347 : preparse_data_builder_scope.SetSkippableFunction(
348 146876 : function_scope, GetLastFunctionLiteralId() - func_id);
349 : }
350 : }
351 :
352 421646 : 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 : 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 421646 : return Expression::Default();
370 : }
371 :
372 2509990 : void PreParser::ParseStatementListAndLogFunction(
373 : PreParserFormalParameters* formals) {
374 5019348 : PreParserScopedStatementList body(pointer_buffer());
375 2509990 : ParseStatementList(&body, Token::RBRACE);
376 :
377 : // Position right after terminal '}'.
378 : DCHECK_IMPLIES(!has_error(), scanner()->peek() == Token::RBRACE);
379 2509674 : 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 2509674 : GetLastFunctionLiteralId());
383 2509674 : }
384 :
385 128265 : PreParserBlock PreParser::BuildParameterInitializationBlock(
386 : const PreParserFormalParameters& parameters) {
387 : DCHECK(!parameters.is_simple);
388 : DCHECK(scope()->is_function_scope());
389 257144 : if (scope()->AsDeclarationScope()->calls_sloppy_eval() &&
390 1168 : 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 1162 : 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 128292 : return PreParserBlock::Default();
407 : }
408 :
409 0 : bool PreParser::IdentifierEquals(const PreParserIdentifier& identifier,
410 : const AstRawString* other) {
411 1568438 : return identifier.string_ == other;
412 : }
413 :
414 : } // namespace internal
415 178779 : } // namespace v8
|