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