Line data Source code
1 : // Copyright 2015 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 "src/ast/ast.h"
6 : #include "src/message-template.h"
7 : #include "src/objects-inl.h"
8 : #include "src/parsing/expression-scope-reparenter.h"
9 : #include "src/parsing/parser.h"
10 :
11 : namespace v8 {
12 :
13 : namespace internal {
14 :
15 : // An AST visitor which performs declaration and assignment related tasks,
16 : // particularly for destructuring patterns:
17 : //
18 : // 1. Declares variables from variable proxies (particularly for destructuring
19 : // declarations),
20 : // 2. Marks destructuring-assigned variable proxies as assigned, and
21 : // 3. Rewrites scopes for parameters containing a sloppy eval.
22 : //
23 : // Historically this also rewrote destructuring assignments/declarations as a
24 : // block of multiple assignments, hence the named, however this is now done
25 : // during bytecode generation.
26 : //
27 : // TODO(leszeks): Rename or remove this class
28 : class PatternRewriter final : public AstVisitor<PatternRewriter> {
29 : public:
30 : // Limit the allowed number of local variables in a function. The hard limit
31 : // is that offsets computed by FullCodeGenerator::StackOperand and similar
32 : // functions are ints, and they should not overflow. In addition, accessing
33 : // local variables creates user-controlled constants in the generated code,
34 : // and we don't want too much user-controlled memory inside the code (this was
35 : // the reason why this limit was introduced in the first place; see
36 : // https://codereview.chromium.org/7003030/ ).
37 : static const int kMaxNumFunctionLocals = 4194303; // 2^22-1
38 :
39 : typedef Parser::DeclarationDescriptor DeclarationDescriptor;
40 :
41 : static void InitializeVariables(
42 : Parser* parser, const DeclarationDescriptor* declaration_descriptor,
43 : const Parser::DeclarationParsingResult::Declaration* declaration,
44 : ZonePtrList<const AstRawString>* names);
45 :
46 : private:
47 : PatternRewriter(Parser* parser, const DeclarationDescriptor* descriptor,
48 : ZonePtrList<const AstRawString>* names, bool has_initializer,
49 : int initializer_position = kNoSourcePosition,
50 : bool declares_parameter_containing_sloppy_eval = false)
51 : : parser_(parser),
52 : descriptor_(descriptor),
53 : names_(names),
54 : initializer_position_(initializer_position),
55 : has_initializer_(has_initializer),
56 : declares_parameter_containing_sloppy_eval_(
57 9316654 : declares_parameter_containing_sloppy_eval) {}
58 :
59 : #define DECLARE_VISIT(type) void Visit##type(v8::internal::type* node);
60 : // Visiting functions for AST nodes make this an AstVisitor.
61 : AST_NODE_LIST(DECLARE_VISIT)
62 : #undef DECLARE_VISIT
63 :
64 9441268 : void RecurseIntoSubpattern(AstNode* pattern) { Visit(pattern); }
65 :
66 : Expression* Visit(Assignment* assign) {
67 : if (parser_->has_error()) return parser_->FailureExpression();
68 : DCHECK_EQ(Token::ASSIGN, assign->op());
69 :
70 : Expression* pattern = assign->target();
71 : if (pattern->IsObjectLiteral()) {
72 : VisitObjectLiteral(pattern->AsObjectLiteral());
73 : } else {
74 : DCHECK(pattern->IsArrayLiteral());
75 : VisitArrayLiteral(pattern->AsArrayLiteral());
76 : }
77 : return assign;
78 : }
79 :
80 : void RewriteParameterScopes(Expression* expr);
81 :
82 : AstNodeFactory* factory() const { return parser_->factory(); }
83 : AstValueFactory* ast_value_factory() const {
84 : return parser_->ast_value_factory();
85 : }
86 :
87 : std::vector<void*>* pointer_buffer() { return parser_->pointer_buffer(); }
88 :
89 194993 : Zone* zone() const { return parser_->zone(); }
90 9349014 : Scope* scope() const { return parser_->scope(); }
91 :
92 : Parser* const parser_;
93 : const DeclarationDescriptor* descriptor_;
94 : ZonePtrList<const AstRawString>* names_;
95 : const int initializer_position_;
96 : const bool has_initializer_;
97 : const bool declares_parameter_containing_sloppy_eval_;
98 :
99 18882786 : DEFINE_AST_VISITOR_MEMBERS_WITHOUT_STACKOVERFLOW()
100 : };
101 :
102 9370762 : void Parser::InitializeVariables(
103 7362705 : ScopedPtrList<Statement>* statements,
104 : const DeclarationDescriptor* declaration_descriptor,
105 : const DeclarationParsingResult::Declaration* declaration,
106 : ZonePtrList<const AstRawString>* names) {
107 18741513 : if (has_error()) return;
108 : PatternRewriter::InitializeVariables(this, declaration_descriptor,
109 9316678 : declaration, names);
110 :
111 9316795 : if (declaration->initializer) {
112 7362879 : int pos = declaration->value_beg_position;
113 7362879 : if (pos == kNoSourcePosition) {
114 353599 : pos = declaration->initializer_position;
115 : }
116 : Assignment* assignment = factory()->NewAssignment(
117 7362879 : Token::INIT, declaration->pattern, declaration->initializer, pos);
118 7362762 : statements->Add(factory()->NewExpressionStatement(assignment, pos));
119 : }
120 : }
121 :
122 9316654 : void PatternRewriter::InitializeVariables(
123 : Parser* parser, const DeclarationDescriptor* declaration_descriptor,
124 : const Parser::DeclarationParsingResult::Declaration* declaration,
125 : ZonePtrList<const AstRawString>* names) {
126 : PatternRewriter rewriter(parser, declaration_descriptor, names,
127 : declaration->initializer != nullptr,
128 : declaration->initializer_position,
129 9372423 : declaration_descriptor->kind == PARAMETER_VARIABLE &&
130 9372423 : parser->scope()->is_block_scope());
131 :
132 9316654 : rewriter.RecurseIntoSubpattern(declaration->pattern);
133 9316814 : }
134 :
135 19216913 : void PatternRewriter::VisitVariableProxy(VariableProxy* proxy) {
136 : DCHECK_NOT_NULL(descriptor_);
137 :
138 1265 : Scope* target_scope = scope();
139 9348559 : if (declares_parameter_containing_sloppy_eval_) {
140 : // When an extra declaration scope needs to be inserted to account for
141 : // a sloppy eval in a default parameter or function body, the parameter
142 : // needs to be declared in the function's scope, not in the varblock
143 : // scope which will be used for the initializer expression.
144 : DCHECK_EQ(descriptor_->mode, VariableMode::kLet);
145 : target_scope = target_scope->outer_scope();
146 : }
147 : Scope* var_init_scope = scope();
148 :
149 : #ifdef DEBUG
150 : // Calculate the scope we expect the variable to be declared in, for DCHECKs.
151 : Scope* expected_declaration_scope =
152 : declares_parameter_containing_sloppy_eval_
153 : ? scope()->outer_scope()
154 : : (IsLexicalVariableMode(descriptor_->mode)
155 : ? scope()
156 : : scope()->GetDeclarationScope());
157 : #endif
158 :
159 : // Declare variable.
160 : // Note that we *always* must treat the initial value via a separate init
161 : // assignment for variables and constants because the value must be assigned
162 : // when the variable is encountered in the source. But the variable/constant
163 : // is declared (and set to 'undefined') upon entering the function within
164 : // which the variable or constant is declared. Only function variables have
165 : // an initial value in the declaration (because they are initialized upon
166 : // entering the function).
167 :
168 : // A declaration of the form:
169 : //
170 : // var v = x;
171 : //
172 : // is syntactic sugar for:
173 : //
174 : // var v; v = x;
175 : //
176 : // In particular, we need to re-lookup 'v' if it may be a different 'v' than
177 : // the 'v' in the declaration (e.g., if we are inside a 'with' statement or
178 : // 'catch' block).
179 : //
180 : // For 'let' and 'const' declared variables the initialization always assigns
181 : // to the declared variable. But for var initializations that are declared in
182 : // a different scope we need to do a new lookup, so clone the variable for the
183 : // declaration and don't consider the original variable resolved.
184 15372672 : if (has_initializer_ && descriptor_->mode == VariableMode::kVar &&
185 : !var_init_scope->is_declaration_scope()) {
186 : DCHECK_EQ(target_scope->GetDeclarationScope(), expected_declaration_scope);
187 : // The cloned variable is not added to the unresolved list of the target
188 : // scope, as it is about to be resolved by the declaration. The original
189 : // variable will be left unresolved for now.
190 382296 : var_init_scope->AddUnresolved(proxy);
191 : proxy = factory()->NewVariableProxy(proxy->raw_name(), NORMAL_VARIABLE,
192 764594 : proxy->position());
193 : }
194 :
195 : parser_->DeclareVariable(
196 : proxy, descriptor_->kind, descriptor_->mode,
197 9348603 : Variable::DefaultInitializationFlag(descriptor_->mode), target_scope,
198 18697206 : descriptor_->declaration_pos);
199 :
200 18697308 : if (parser_->has_error()) return;
201 9291064 : Variable* var = proxy->var();
202 : DCHECK_NOT_NULL(var);
203 : DCHECK(proxy->is_resolved());
204 : DCHECK_EQ(var->scope(), expected_declaration_scope);
205 : DCHECK_NE(initializer_position_, kNoSourcePosition);
206 9291064 : var->set_initializer_position(initializer_position_);
207 :
208 9291064 : if (var->scope()->num_var() > kMaxNumFunctionLocals) {
209 0 : parser_->ReportMessage(MessageTemplate::kTooManyVariables);
210 0 : return;
211 : }
212 9291064 : if (names_) {
213 194993 : names_->Add(proxy->raw_name(), zone());
214 : }
215 : }
216 :
217 : // When an extra declaration scope needs to be inserted to account for
218 : // a sloppy eval in a default parameter or function body, the expressions
219 : // needs to be in that new inner scope which was added after initial
220 : // parsing.
221 22899 : void PatternRewriter::RewriteParameterScopes(Expression* expr) {
222 22444 : if (declares_parameter_containing_sloppy_eval_) {
223 455 : ReparentExpressionScope(parser_->stack_limit(), expr, scope());
224 : }
225 22444 : }
226 :
227 47535 : void PatternRewriter::VisitObjectLiteral(ObjectLiteral* pattern) {
228 161609 : for (ObjectLiteralProperty* property : *pattern->properties()) {
229 66538 : Expression* key = property->key();
230 66538 : if (!key->IsLiteral()) {
231 : // Computed property names contain expressions which might require
232 : // scope rewriting.
233 2638 : RewriteParameterScopes(key);
234 : }
235 : RecurseIntoSubpattern(property->value());
236 : }
237 47536 : }
238 :
239 22749 : void PatternRewriter::VisitArrayLiteral(ArrayLiteral* node) {
240 81434 : for (Expression* value : *node->values()) {
241 35936 : if (value->IsTheHoleLiteral()) continue;
242 : RecurseIntoSubpattern(value);
243 : }
244 22749 : }
245 :
246 39612 : void PatternRewriter::VisitAssignment(Assignment* node) {
247 : DCHECK_EQ(Token::ASSIGN, node->op());
248 :
249 : // Initializer may have been parsed in the wrong scope.
250 19806 : RewriteParameterScopes(node->value());
251 :
252 : RecurseIntoSubpattern(node->target());
253 19807 : }
254 :
255 2684 : void PatternRewriter::VisitSpread(Spread* node) {
256 : RecurseIntoSubpattern(node->expression());
257 2684 : }
258 :
259 : // =============== UNREACHABLE =============================
260 :
261 : #define NOT_A_PATTERN(Node) \
262 : void PatternRewriter::Visit##Node(v8::internal::Node*) { UNREACHABLE(); }
263 :
264 0 : NOT_A_PATTERN(BinaryOperation)
265 0 : NOT_A_PATTERN(NaryOperation)
266 0 : NOT_A_PATTERN(Block)
267 0 : NOT_A_PATTERN(BreakStatement)
268 0 : NOT_A_PATTERN(Call)
269 0 : NOT_A_PATTERN(CallNew)
270 0 : NOT_A_PATTERN(CallRuntime)
271 0 : NOT_A_PATTERN(ClassLiteral)
272 0 : NOT_A_PATTERN(CompareOperation)
273 0 : NOT_A_PATTERN(CompoundAssignment)
274 0 : NOT_A_PATTERN(Conditional)
275 0 : NOT_A_PATTERN(ContinueStatement)
276 0 : NOT_A_PATTERN(CountOperation)
277 0 : NOT_A_PATTERN(DebuggerStatement)
278 0 : NOT_A_PATTERN(DoExpression)
279 0 : NOT_A_PATTERN(DoWhileStatement)
280 0 : NOT_A_PATTERN(EmptyStatement)
281 0 : NOT_A_PATTERN(EmptyParentheses)
282 0 : NOT_A_PATTERN(ExpressionStatement)
283 0 : NOT_A_PATTERN(ForInStatement)
284 0 : NOT_A_PATTERN(ForOfStatement)
285 0 : NOT_A_PATTERN(ForStatement)
286 0 : NOT_A_PATTERN(FunctionDeclaration)
287 0 : NOT_A_PATTERN(FunctionLiteral)
288 0 : NOT_A_PATTERN(GetTemplateObject)
289 0 : NOT_A_PATTERN(IfStatement)
290 0 : NOT_A_PATTERN(ImportCallExpression)
291 0 : NOT_A_PATTERN(Literal)
292 0 : NOT_A_PATTERN(NativeFunctionLiteral)
293 0 : NOT_A_PATTERN(Property)
294 0 : NOT_A_PATTERN(RegExpLiteral)
295 0 : NOT_A_PATTERN(ResolvedProperty)
296 0 : NOT_A_PATTERN(ReturnStatement)
297 0 : NOT_A_PATTERN(SloppyBlockFunctionStatement)
298 0 : NOT_A_PATTERN(StoreInArrayLiteral)
299 0 : NOT_A_PATTERN(SuperPropertyReference)
300 0 : NOT_A_PATTERN(SuperCallReference)
301 0 : NOT_A_PATTERN(SwitchStatement)
302 0 : NOT_A_PATTERN(TemplateLiteral)
303 0 : NOT_A_PATTERN(ThisFunction)
304 0 : NOT_A_PATTERN(Throw)
305 0 : NOT_A_PATTERN(TryCatchStatement)
306 0 : NOT_A_PATTERN(TryFinallyStatement)
307 0 : NOT_A_PATTERN(UnaryOperation)
308 0 : NOT_A_PATTERN(VariableDeclaration)
309 0 : NOT_A_PATTERN(WhileStatement)
310 0 : NOT_A_PATTERN(WithStatement)
311 0 : NOT_A_PATTERN(Yield)
312 0 : NOT_A_PATTERN(YieldStar)
313 0 : NOT_A_PATTERN(Await)
314 0 : NOT_A_PATTERN(InitializeClassMembersStatement)
315 :
316 : #undef NOT_A_PATTERN
317 : } // namespace internal
318 183867 : } // namespace v8
|