Line data Source code
1 : // Copyright 2012 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 : #ifndef V8_AST_SCOPES_H_
6 : #define V8_AST_SCOPES_H_
7 :
8 : #include "src/ast/ast.h"
9 : #include "src/base/compiler-specific.h"
10 : #include "src/base/hashmap.h"
11 : #include "src/base/threaded-list.h"
12 : #include "src/function-kind.h"
13 : #include "src/globals.h"
14 : #include "src/objects.h"
15 : #include "src/pointer-with-payload.h"
16 : #include "src/zone/zone.h"
17 :
18 : namespace v8 {
19 : namespace internal {
20 :
21 : class AstNodeFactory;
22 : class AstValueFactory;
23 : class AstRawString;
24 : class Declaration;
25 : class ParseInfo;
26 : class Parser;
27 : class PreparseDataBuilder;
28 : class SloppyBlockFunctionStatement;
29 : class Statement;
30 : class StringSet;
31 : class VariableProxy;
32 :
33 : typedef base::ThreadedList<VariableProxy, VariableProxy::UnresolvedNext>
34 : UnresolvedList;
35 :
36 : // A hash map to support fast variable declaration and lookup.
37 1 : class VariableMap : public ZoneHashMap {
38 : public:
39 : explicit VariableMap(Zone* zone);
40 :
41 : Variable* Declare(Zone* zone, Scope* scope, const AstRawString* name,
42 : VariableMode mode, VariableKind kind,
43 : InitializationFlag initialization_flag,
44 : MaybeAssignedFlag maybe_assigned_flag, bool* was_added);
45 :
46 : V8_EXPORT_PRIVATE Variable* Lookup(const AstRawString* name);
47 : void Remove(Variable* var);
48 : void Add(Zone* zone, Variable* var);
49 : };
50 :
51 : class Scope;
52 :
53 : template <>
54 : struct PointerWithPayloadTraits<Scope> {
55 : static constexpr int value = 1;
56 : };
57 :
58 : // Global invariants after AST construction: Each reference (i.e. identifier)
59 : // to a JavaScript variable (including global properties) is represented by a
60 : // VariableProxy node. Immediately after AST construction and before variable
61 : // allocation, most VariableProxy nodes are "unresolved", i.e. not bound to a
62 : // corresponding variable (though some are bound during parse time). Variable
63 : // allocation binds each unresolved VariableProxy to one Variable and assigns
64 : // a location. Note that many VariableProxy nodes may refer to the same Java-
65 : // Script variable.
66 :
67 : // JS environments are represented in the parser using Scope, DeclarationScope
68 : // and ModuleScope. DeclarationScope is used for any scope that hosts 'var'
69 : // declarations. This includes script, module, eval, varblock, and function
70 : // scope. ModuleScope further specializes DeclarationScope.
71 1 : class V8_EXPORT_PRIVATE Scope : public NON_EXPORTED_BASE(ZoneObject) {
72 : public:
73 : // ---------------------------------------------------------------------------
74 : // Construction
75 :
76 : Scope(Zone* zone, Scope* outer_scope, ScopeType scope_type);
77 :
78 : #ifdef DEBUG
79 : // The scope name is only used for printing/debugging.
80 : void SetScopeName(const AstRawString* scope_name) {
81 : scope_name_ = scope_name;
82 : }
83 : #endif
84 :
85 : DeclarationScope* AsDeclarationScope();
86 : const DeclarationScope* AsDeclarationScope() const;
87 : ModuleScope* AsModuleScope();
88 : const ModuleScope* AsModuleScope() const;
89 : ClassScope* AsClassScope();
90 : const ClassScope* AsClassScope() const;
91 :
92 : class Snapshot final {
93 : public:
94 : Snapshot()
95 : : outer_scope_and_calls_eval_(nullptr, false),
96 : top_unresolved_(),
97 : top_local_() {
98 : DCHECK(IsCleared());
99 : }
100 : inline explicit Snapshot(Scope* scope);
101 :
102 3117879 : ~Snapshot() {
103 : // If we're still active, there was no arrow function. In that case outer
104 : // calls eval if it already called eval before this snapshot started, or
105 : // if the code during the snapshot called eval.
106 6102241 : if (!IsCleared() && outer_scope_and_calls_eval_.GetPayload()) {
107 : RestoreEvalFlag();
108 : }
109 : }
110 :
111 : void RestoreEvalFlag() {
112 : outer_scope_and_calls_eval_->scope_calls_eval_ =
113 188674 : outer_scope_and_calls_eval_.GetPayload();
114 : }
115 :
116 : void Reparent(DeclarationScope* new_parent);
117 : bool IsCleared() const {
118 : return outer_scope_and_calls_eval_.GetPointer() == nullptr;
119 : }
120 :
121 : void Clear() {
122 : outer_scope_and_calls_eval_.SetPointer(nullptr);
123 : #ifdef DEBUG
124 : outer_scope_and_calls_eval_.SetPayload(false);
125 : top_inner_scope_ = nullptr;
126 : top_local_ = base::ThreadedList<Variable>::Iterator();
127 : top_unresolved_ = UnresolvedList::Iterator();
128 : #endif
129 : }
130 :
131 : private:
132 : // During tracking calls_eval caches whether the outer scope called eval.
133 : // Upon move assignment we store whether the new inner scope calls eval into
134 : // the move target calls_eval bit, and restore calls eval on the outer
135 : // scope.
136 : PointerWithPayload<Scope, bool, 1> outer_scope_and_calls_eval_;
137 : Scope* top_inner_scope_;
138 : UnresolvedList::Iterator top_unresolved_;
139 : base::ThreadedList<Variable>::Iterator top_local_;
140 :
141 : // Disallow copy and move.
142 : Snapshot(const Snapshot&) = delete;
143 : Snapshot(Snapshot&&) = delete;
144 : };
145 :
146 : enum class DeserializationMode { kIncludingVariables, kScopesOnly };
147 :
148 : static Scope* DeserializeScopeChain(Isolate* isolate, Zone* zone,
149 : ScopeInfo scope_info,
150 : DeclarationScope* script_scope,
151 : AstValueFactory* ast_value_factory,
152 : DeserializationMode deserialization_mode);
153 :
154 : // Checks if the block scope is redundant, i.e. it does not contain any
155 : // block scoped declarations. In that case it is removed from the scope
156 : // tree and its children are reparented.
157 : Scope* FinalizeBlockScope();
158 :
159 : // Inserts outer_scope into this scope's scope chain (and removes this
160 : // from the current outer_scope_'s inner scope list).
161 : // Assumes outer_scope_ is non-null.
162 : void ReplaceOuterScope(Scope* outer_scope);
163 :
164 : Zone* zone() const { return zone_; }
165 :
166 : void SetMustUsePreparseData() {
167 115326 : if (must_use_preparsed_scope_data_) {
168 : return;
169 : }
170 84195 : must_use_preparsed_scope_data_ = true;
171 84195 : if (outer_scope_) {
172 : outer_scope_->SetMustUsePreparseData();
173 : }
174 : }
175 :
176 : bool must_use_preparsed_scope_data() const {
177 : return must_use_preparsed_scope_data_;
178 : }
179 :
180 : // ---------------------------------------------------------------------------
181 : // Declarations
182 :
183 : // Lookup a variable in this scope. Returns the variable or nullptr if not
184 : // found.
185 : Variable* LookupLocal(const AstRawString* name) {
186 : DCHECK(scope_info_.is_null());
187 86993234 : return variables_.Lookup(name);
188 : }
189 :
190 : Variable* LookupInScopeInfo(const AstRawString* name, Scope* cache);
191 :
192 : // Declare a local variable in this scope. If the variable has been
193 : // declared before, the previously declared variable is returned.
194 : Variable* DeclareLocal(const AstRawString* name, VariableMode mode,
195 : VariableKind kind, bool* was_added,
196 : InitializationFlag init_flag = kCreatedInitialized);
197 :
198 : Variable* DeclareVariable(Declaration* declaration, const AstRawString* name,
199 : int pos, VariableMode mode, VariableKind kind,
200 : InitializationFlag init, bool* was_added,
201 : bool* sloppy_mode_block_scope_function_redefinition,
202 : bool* ok);
203 :
204 : // Returns nullptr if there was a declaration conflict.
205 : Variable* DeclareVariableName(const AstRawString* name, VariableMode mode,
206 : bool* was_added,
207 : VariableKind kind = NORMAL_VARIABLE);
208 : Variable* DeclareCatchVariableName(const AstRawString* name);
209 :
210 : // Declarations list.
211 18193134 : base::ThreadedList<Declaration>* declarations() { return &decls_; }
212 :
213 : base::ThreadedList<Variable>* locals() { return &locals_; }
214 :
215 : // Create a new unresolved variable.
216 96177 : VariableProxy* NewUnresolved(AstNodeFactory* factory,
217 : const AstRawString* name, int start_pos,
218 : VariableKind kind = NORMAL_VARIABLE) {
219 : // Note that we must not share the unresolved variables with
220 : // the same name because they may be removed selectively via
221 : // RemoveUnresolved().
222 : DCHECK(!already_resolved_);
223 : DCHECK_EQ(factory->zone(), zone());
224 : VariableProxy* proxy = factory->NewVariableProxy(name, kind, start_pos);
225 96177 : AddUnresolved(proxy);
226 96177 : return proxy;
227 : }
228 :
229 : void AddUnresolved(VariableProxy* proxy);
230 :
231 : // Removes an unresolved variable from the list so it can be readded to
232 : // another list. This is used to reparent parameter initializers that contain
233 : // sloppy eval.
234 : bool RemoveUnresolved(VariableProxy* var);
235 :
236 : // Deletes an unresolved variable. The variable proxy cannot be reused for
237 : // another list later. During parsing, an unresolved variable may have been
238 : // added optimistically, but then only the variable name was used (typically
239 : // for labels and arrow function parameters). If the variable was not
240 : // declared, the addition introduced a new unresolved variable which may end
241 : // up being allocated globally as a "ghost" variable. DeleteUnresolved removes
242 : // such a variable again if it was added; otherwise this is a no-op.
243 : void DeleteUnresolved(VariableProxy* var);
244 :
245 : // Creates a new temporary variable in this scope's TemporaryScope. The
246 : // name is only used for printing and cannot be used to find the variable.
247 : // In particular, the only way to get hold of the temporary is by keeping the
248 : // Variable* around. The name should not clash with a legitimate variable
249 : // names.
250 : // TODO(verwaest): Move to DeclarationScope?
251 : Variable* NewTemporary(const AstRawString* name);
252 :
253 : // Find variable with (variable->mode() <= |mode_limit|) that was declared in
254 : // |scope|. This is used to catch patterns like `try{}catch(e){let e;}` and
255 : // function([e]) { let e }, which are errors even though the two 'e's are each
256 : // time declared in different scopes. Returns the first duplicate variable
257 : // name if there is one, nullptr otherwise.
258 : const AstRawString* FindVariableDeclaredIn(Scope* scope,
259 : VariableMode mode_limit);
260 :
261 : // ---------------------------------------------------------------------------
262 : // Scope-specific info.
263 :
264 : // Inform the scope and outer scopes that the corresponding code contains an
265 : // eval call.
266 : void RecordEvalCall() {
267 148386 : scope_calls_eval_ = true;
268 : }
269 :
270 : void RecordInnerScopeEvalCall() {
271 223681 : inner_scope_calls_eval_ = true;
272 705796 : for (Scope* scope = outer_scope(); scope != nullptr;
273 : scope = scope->outer_scope()) {
274 531513 : if (scope->inner_scope_calls_eval_) return;
275 482115 : scope->inner_scope_calls_eval_ = true;
276 : }
277 : }
278 :
279 : // Set the language mode flag (unless disabled by a global flag).
280 : void SetLanguageMode(LanguageMode language_mode) {
281 : DCHECK(!is_module_scope() || is_strict(language_mode));
282 : set_language_mode(language_mode);
283 : }
284 :
285 : // Inform the scope that the scope may execute declarations nonlinearly.
286 : // Currently, the only nonlinear scope is a switch statement. The name is
287 : // more general in case something else comes up with similar control flow,
288 : // for example the ability to break out of something which does not have
289 : // its own lexical scope.
290 : // The bit does not need to be stored on the ScopeInfo because none of
291 : // the three compilers will perform hole check elimination on a variable
292 : // located in VariableLocation::CONTEXT. So, direct eval and closures
293 : // will not expose holes.
294 137336 : void SetNonlinear() { scope_nonlinear_ = true; }
295 :
296 : // Position in the source where this scope begins and ends.
297 : //
298 : // * For the scope of a with statement
299 : // with (obj) stmt
300 : // start position: start position of first token of 'stmt'
301 : // end position: end position of last token of 'stmt'
302 : // * For the scope of a block
303 : // { stmts }
304 : // start position: start position of '{'
305 : // end position: end position of '}'
306 : // * For the scope of a function literal or decalaration
307 : // function fun(a,b) { stmts }
308 : // start position: start position of '('
309 : // end position: end position of '}'
310 : // * For the scope of a catch block
311 : // try { stms } catch(e) { stmts }
312 : // start position: start position of '('
313 : // end position: end position of ')'
314 : // * For the scope of a for-statement
315 : // for (let x ...) stmt
316 : // start position: start position of '('
317 : // end position: end position of last token of 'stmt'
318 : // * For the scope of a switch statement
319 : // switch (tag) { cases }
320 : // start position: start position of '{'
321 : // end position: end position of '}'
322 : int start_position() const { return start_position_; }
323 : void set_start_position(int statement_pos) {
324 13595784 : start_position_ = statement_pos;
325 : }
326 : int end_position() const { return end_position_; }
327 : void set_end_position(int statement_pos) {
328 14282221 : end_position_ = statement_pos;
329 : }
330 :
331 : // Scopes created for desugaring are hidden. I.e. not visible to the debugger.
332 232003 : bool is_hidden() const { return is_hidden_; }
333 349733 : void set_is_hidden() { is_hidden_ = true; }
334 :
335 : void ForceContextAllocationForParameters() {
336 : DCHECK(!already_resolved_);
337 : force_context_allocation_for_parameters_ = true;
338 : }
339 : bool has_forced_context_allocation_for_parameters() const {
340 2698738 : return force_context_allocation_for_parameters_;
341 : }
342 :
343 : // ---------------------------------------------------------------------------
344 : // Predicates.
345 :
346 : // Specific scope types.
347 13822010 : bool is_eval_scope() const { return scope_type_ == EVAL_SCOPE; }
348 24552714 : bool is_function_scope() const { return scope_type_ == FUNCTION_SCOPE; }
349 : bool is_module_scope() const { return scope_type_ == MODULE_SCOPE; }
350 : bool is_script_scope() const { return scope_type_ == SCRIPT_SCOPE; }
351 : bool is_catch_scope() const { return scope_type_ == CATCH_SCOPE; }
352 : bool is_block_scope() const {
353 25269524 : return scope_type_ == BLOCK_SCOPE || scope_type_ == CLASS_SCOPE;
354 : }
355 20051778 : bool is_with_scope() const { return scope_type_ == WITH_SCOPE; }
356 156886709 : bool is_declaration_scope() const { return is_declaration_scope_; }
357 : bool is_class_scope() const { return scope_type_ == CLASS_SCOPE; }
358 :
359 218572 : bool inner_scope_calls_eval() const { return inner_scope_calls_eval_; }
360 : bool IsAsmModule() const;
361 : // Returns true if this scope or any inner scopes that might be eagerly
362 : // compiled are asm modules.
363 : bool ContainsAsmModule() const;
364 : // Does this scope have the potential to execute declarations non-linearly?
365 966750 : bool is_nonlinear() const { return scope_nonlinear_; }
366 : // Returns if we need to force a context because the current scope is stricter
367 : // than the outerscope. We need this to properly track the language mode using
368 : // the context. This is required in ICs where we lookup the language mode
369 : // from the context.
370 : bool ForceContextForLanguageMode() const {
371 : // For function scopes we need not force a context since the language mode
372 : // can be obtained from the closure. Script scopes always have a context.
373 5401761 : if (scope_type_ == FUNCTION_SCOPE || scope_type_ == SCRIPT_SCOPE) {
374 : return false;
375 : }
376 : DCHECK_NOT_NULL(outer_scope_);
377 4648898 : return (language_mode() > outer_scope_->language_mode());
378 : }
379 :
380 : // Whether this needs to be represented by a runtime context.
381 : bool NeedsContext() const {
382 : // Catch scopes always have heap slots.
383 : DCHECK_IMPLIES(is_catch_scope(), num_heap_slots() > 0);
384 : DCHECK_IMPLIES(is_with_scope(), num_heap_slots() > 0);
385 : DCHECK_IMPLIES(ForceContextForLanguageMode(), num_heap_slots() > 0);
386 1337220 : return num_heap_slots() > 0;
387 : }
388 :
389 : // Use Scope::ForEach for depth first traversal of scopes.
390 : // Before:
391 : // void Scope::VisitRecursively() {
392 : // DoSomething();
393 : // for (Scope* s = inner_scope_; s != nullptr; s = s->sibling_) {
394 : // if (s->ShouldContinue()) continue;
395 : // s->VisitRecursively();
396 : // }
397 : // }
398 : //
399 : // After:
400 : // void Scope::VisitIteratively() {
401 : // this->ForEach([](Scope* s) {
402 : // s->DoSomething();
403 : // return s->ShouldContinue() ? kContinue : kDescend;
404 : // });
405 : // }
406 : template <typename FunctionType>
407 : V8_INLINE void ForEach(FunctionType callback);
408 : enum Iteration {
409 : // Continue the iteration on the same level, do not recurse/descent into
410 : // inner scopes.
411 : kContinue,
412 : // Recurse/descend into inner scopes.
413 : kDescend
414 : };
415 :
416 : // ---------------------------------------------------------------------------
417 : // Accessors.
418 :
419 : // The type of this scope.
420 : ScopeType scope_type() const { return scope_type_; }
421 :
422 : // The language mode of this scope.
423 : LanguageMode language_mode() const {
424 112972412 : return is_strict_ ? LanguageMode::kStrict : LanguageMode::kSloppy;
425 : }
426 :
427 : // inner_scope() and sibling() together implement the inner scope list of a
428 : // scope. Inner scope points to the an inner scope of the function, and
429 : // "sibling" points to a next inner scope of the outer scope of this scope.
430 : Scope* inner_scope() const { return inner_scope_; }
431 : Scope* sibling() const { return sibling_; }
432 :
433 : // The scope immediately surrounding this scope, or nullptr.
434 : Scope* outer_scope() const { return outer_scope_; }
435 :
436 : Variable* catch_variable() const {
437 : DCHECK(is_catch_scope());
438 : DCHECK_EQ(1, num_var());
439 69036 : return static_cast<Variable*>(variables_.Start()->value);
440 : }
441 :
442 : bool ShouldBanArguments();
443 :
444 : // ---------------------------------------------------------------------------
445 : // Variable allocation.
446 :
447 : // Result of variable allocation.
448 : int num_stack_slots() const { return num_stack_slots_; }
449 : int num_heap_slots() const { return num_heap_slots_; }
450 :
451 : int ContextLocalCount() const;
452 :
453 : // Determine if we can parse a function literal in this scope lazily without
454 : // caring about the unresolved variables within.
455 : bool AllowsLazyParsingWithoutUnresolvedVariables(const Scope* outer) const;
456 :
457 : // The number of contexts between this and scope; zero if this == scope.
458 : int ContextChainLength(Scope* scope) const;
459 :
460 : // The number of contexts between this and the outermost context that has a
461 : // sloppy eval call. One if this->calls_sloppy_eval().
462 : int ContextChainLengthUntilOutermostSloppyEval() const;
463 :
464 : // Find the closest class scope in the current scope and outer scopes. If no
465 : // class scope is found, nullptr will be returned.
466 : ClassScope* GetClassScope();
467 :
468 : // Find the first function, script, eval or (declaration) block scope. This is
469 : // the scope where var declarations will be hoisted to in the implementation.
470 : DeclarationScope* GetDeclarationScope();
471 :
472 : // Find the first non-block declaration scope. This should be either a script,
473 : // function, or eval scope. Same as DeclarationScope(), but skips declaration
474 : // "block" scopes. Used for differentiating associated function objects (i.e.,
475 : // the scope for which a function prologue allocates a context) or declaring
476 : // temporaries.
477 : DeclarationScope* GetClosureScope();
478 : const DeclarationScope* GetClosureScope() const;
479 :
480 : // Find the first (non-arrow) function or script scope. This is where
481 : // 'this' is bound, and what determines the function kind.
482 : DeclarationScope* GetReceiverScope();
483 :
484 : // Find the innermost outer scope that needs a context.
485 : Scope* GetOuterScopeWithContext();
486 :
487 : bool HasThisReference() const;
488 :
489 : // Analyze() must have been called once to create the ScopeInfo.
490 : Handle<ScopeInfo> scope_info() const {
491 : DCHECK(!scope_info_.is_null());
492 : return scope_info_;
493 : }
494 :
495 13805044 : int num_var() const { return variables_.occupancy(); }
496 :
497 : // ---------------------------------------------------------------------------
498 : // Debugging.
499 :
500 : #ifdef DEBUG
501 : void Print(int n = 0); // n = indentation; n < 0 => don't print recursively
502 :
503 : // Check that the scope has positions assigned.
504 : void CheckScopePositions();
505 :
506 : // Check that all Scopes in the scope tree use the same Zone.
507 : void CheckZones();
508 : #endif
509 :
510 : // Retrieve `IsSimpleParameterList` of current or outer function.
511 : bool HasSimpleParameters();
512 12757 : void set_is_debug_evaluate_scope() { is_debug_evaluate_scope_ = true; }
513 2867932 : bool is_debug_evaluate_scope() const { return is_debug_evaluate_scope_; }
514 : bool IsSkippableFunctionScope();
515 :
516 : bool RemoveInnerScope(Scope* inner_scope) {
517 : DCHECK_NOT_NULL(inner_scope);
518 4500589 : if (inner_scope == inner_scope_) {
519 4500498 : inner_scope_ = inner_scope_->sibling_;
520 : return true;
521 : }
522 91 : for (Scope* scope = inner_scope_; scope != nullptr;
523 : scope = scope->sibling_) {
524 91 : if (scope->sibling_ == inner_scope) {
525 91 : scope->sibling_ = scope->sibling_->sibling_;
526 : return true;
527 : }
528 : }
529 : return false;
530 : }
531 :
532 339627 : Variable* LookupInScopeOrScopeInfo(const AstRawString* name) {
533 339627 : Variable* var = variables_.Lookup(name);
534 644169 : if (var != nullptr || scope_info_.is_null()) return var;
535 283176 : return LookupInScopeInfo(name, this);
536 : }
537 :
538 : Variable* LookupForTesting(const AstRawString* name) {
539 33640 : for (Scope* scope = this; scope != nullptr; scope = scope->outer_scope()) {
540 33640 : Variable* var = scope->LookupInScopeOrScopeInfo(name);
541 33640 : if (var != nullptr) return var;
542 : }
543 : return nullptr;
544 : }
545 :
546 : protected:
547 : explicit Scope(Zone* zone);
548 :
549 : void set_language_mode(LanguageMode language_mode) {
550 40310248 : is_strict_ = is_strict(language_mode);
551 : }
552 :
553 : private:
554 : Variable* Declare(Zone* zone, const AstRawString* name, VariableMode mode,
555 : VariableKind kind, InitializationFlag initialization_flag,
556 : MaybeAssignedFlag maybe_assigned_flag, bool* was_added) {
557 : Variable* result =
558 33319986 : variables_.Declare(zone, this, name, mode, kind, initialization_flag,
559 34265469 : maybe_assigned_flag, was_added);
560 34265295 : if (*was_added) locals_.Add(result);
561 : return result;
562 : }
563 :
564 : // This method should only be invoked on scopes created during parsing (i.e.,
565 : // not deserialized from a context). Also, since NeedsContext() is only
566 : // returning a valid result after variables are resolved, NeedsScopeInfo()
567 : // should also be invoked after resolution.
568 : bool NeedsScopeInfo() const;
569 :
570 : Variable* NewTemporary(const AstRawString* name,
571 : MaybeAssignedFlag maybe_assigned);
572 :
573 : // Walk the scope chain to find DeclarationScopes; call
574 : // SavePreparseDataForDeclarationScope for each.
575 : void SavePreparseData(Parser* parser);
576 :
577 : // Create a non-local variable with a given name.
578 : // These variables are looked up dynamically at runtime.
579 : Variable* NonLocal(const AstRawString* name, VariableMode mode);
580 :
581 : enum ScopeLookupMode {
582 : kParsedScope,
583 : kDeserializedScope,
584 : };
585 :
586 : // Variable resolution.
587 : // Lookup a variable reference given by name starting with this scope, and
588 : // stopping when reaching the outer_scope_end scope. If the code is executed
589 : // because of a call to 'eval', the context parameter should be set to the
590 : // calling context of 'eval'.
591 : template <ScopeLookupMode mode>
592 : static Variable* Lookup(VariableProxy* proxy, Scope* scope,
593 : Scope* outer_scope_end, Scope* entry_point = nullptr,
594 : bool force_context_allocation = false);
595 : static Variable* LookupWith(VariableProxy* proxy, Scope* scope,
596 : Scope* outer_scope_end, Scope* entry_point,
597 : bool force_context_allocation);
598 : static Variable* LookupSloppyEval(VariableProxy* proxy, Scope* scope,
599 : Scope* outer_scope_end, Scope* entry_point,
600 : bool force_context_allocation);
601 : static void ResolvePreparsedVariable(VariableProxy* proxy, Scope* scope,
602 : Scope* end);
603 : void ResolveTo(ParseInfo* info, VariableProxy* proxy, Variable* var);
604 : void ResolveVariable(ParseInfo* info, VariableProxy* proxy);
605 : V8_WARN_UNUSED_RESULT bool ResolveVariablesRecursively(ParseInfo* info);
606 :
607 : // Finds free variables of this scope. This mutates the unresolved variables
608 : // list along the way, so full resolution cannot be done afterwards.
609 : void AnalyzePartially(DeclarationScope* max_outer_scope,
610 : AstNodeFactory* ast_node_factory,
611 : UnresolvedList* new_unresolved_list);
612 : void CollectNonLocals(DeclarationScope* max_outer_scope, Isolate* isolate,
613 : ParseInfo* info, Handle<StringSet>* non_locals);
614 :
615 : // Predicates.
616 : bool MustAllocate(Variable* var);
617 : bool MustAllocateInContext(Variable* var);
618 :
619 : // Variable allocation.
620 : void AllocateStackSlot(Variable* var);
621 : V8_INLINE void AllocateHeapSlot(Variable* var);
622 : void AllocateNonParameterLocal(Variable* var);
623 : void AllocateDeclaredGlobal(Variable* var);
624 : V8_INLINE void AllocateNonParameterLocalsAndDeclaredGlobals();
625 : void AllocateVariablesRecursively();
626 :
627 : void AllocateScopeInfosRecursively(Isolate* isolate,
628 : MaybeHandle<ScopeInfo> outer_scope);
629 :
630 : void AllocateDebuggerScopeInfos(Isolate* isolate,
631 : MaybeHandle<ScopeInfo> outer_scope);
632 :
633 : // Construct a scope based on the scope info.
634 : Scope(Zone* zone, ScopeType type, Handle<ScopeInfo> scope_info);
635 :
636 : // Construct a catch scope with a binding for the name.
637 : Scope(Zone* zone, const AstRawString* catch_variable_name,
638 : MaybeAssignedFlag maybe_assigned, Handle<ScopeInfo> scope_info);
639 :
640 : void AddInnerScope(Scope* inner_scope) {
641 14150868 : inner_scope->sibling_ = inner_scope_;
642 14150868 : inner_scope_ = inner_scope;
643 14150868 : inner_scope->outer_scope_ = this;
644 : }
645 :
646 : void SetDefaults();
647 :
648 : friend class DeclarationScope;
649 : friend class ClassScope;
650 : friend class ScopeTestHelper;
651 :
652 : Zone* zone_;
653 :
654 : // Scope tree.
655 : Scope* outer_scope_; // the immediately enclosing outer scope, or nullptr
656 : Scope* inner_scope_; // an inner scope of this scope
657 : Scope* sibling_; // a sibling inner scope of the outer scope of this scope.
658 :
659 : // The variables declared in this scope:
660 : //
661 : // All user-declared variables (incl. parameters). For script scopes
662 : // variables may be implicitly 'declared' by being used (possibly in
663 : // an inner scope) with no intervening with statements or eval calls.
664 : VariableMap variables_;
665 : // In case of non-scopeinfo-backed scopes, this contains the variables of the
666 : // map above in order of addition.
667 : base::ThreadedList<Variable> locals_;
668 : // Unresolved variables referred to from this scope. The proxies themselves
669 : // form a linked list of all unresolved proxies.
670 : UnresolvedList unresolved_list_;
671 : // Declarations.
672 : base::ThreadedList<Declaration> decls_;
673 :
674 : // Serialized scope info support.
675 : Handle<ScopeInfo> scope_info_;
676 : // Debugging support.
677 : #ifdef DEBUG
678 : const AstRawString* scope_name_;
679 :
680 : // True if it doesn't need scope resolution (e.g., if the scope was
681 : // constructed based on a serialized scope info or a catch context).
682 : bool already_resolved_;
683 : // True if this scope may contain objects from a temp zone that needs to be
684 : // fixed up.
685 : bool needs_migration_;
686 : #endif
687 :
688 : // Source positions.
689 : int start_position_;
690 : int end_position_;
691 :
692 : // Computed via AllocateVariables.
693 : int num_stack_slots_;
694 : int num_heap_slots_;
695 :
696 : // The scope type.
697 : const ScopeType scope_type_;
698 :
699 : // Scope-specific information computed during parsing.
700 : //
701 : // The language mode of this scope.
702 : STATIC_ASSERT(LanguageModeSize == 2);
703 : bool is_strict_ : 1;
704 : // This scope or a nested catch scope or with scope contain an 'eval' call. At
705 : // the 'eval' call site this scope is the declaration scope.
706 : bool scope_calls_eval_ : 1;
707 : // This scope's declarations might not be executed in order (e.g., switch).
708 : bool scope_nonlinear_ : 1;
709 : bool is_hidden_ : 1;
710 : // Temporary workaround that allows masking of 'this' in debug-evalute scopes.
711 : bool is_debug_evaluate_scope_ : 1;
712 :
713 : // True if one of the inner scopes or the scope itself calls eval.
714 : bool inner_scope_calls_eval_ : 1;
715 : bool force_context_allocation_ : 1;
716 : bool force_context_allocation_for_parameters_ : 1;
717 :
718 : // True if it holds 'var' declarations.
719 : bool is_declaration_scope_ : 1;
720 :
721 : bool must_use_preparsed_scope_data_ : 1;
722 : };
723 :
724 1 : class V8_EXPORT_PRIVATE DeclarationScope : public Scope {
725 : public:
726 : DeclarationScope(Zone* zone, Scope* outer_scope, ScopeType scope_type,
727 : FunctionKind function_kind = kNormalFunction);
728 : DeclarationScope(Zone* zone, ScopeType scope_type,
729 : Handle<ScopeInfo> scope_info);
730 : // Creates a script scope.
731 : DeclarationScope(Zone* zone, AstValueFactory* ast_value_factory);
732 :
733 281179 : FunctionKind function_kind() const { return function_kind_; }
734 :
735 : bool is_arrow_scope() const {
736 18650668 : return is_function_scope() && IsArrowFunction(function_kind_);
737 : }
738 :
739 : // Inform the scope that the corresponding code uses "super".
740 : void RecordSuperPropertyUsage() {
741 : DCHECK(IsConciseMethod(function_kind()) ||
742 : IsAccessorFunction(function_kind()) ||
743 : IsClassConstructor(function_kind()));
744 7245 : scope_uses_super_property_ = true;
745 : }
746 :
747 : // Does this scope access "super" property (super.foo).
748 3934986 : bool NeedsHomeObject() const {
749 7867376 : return scope_uses_super_property_ ||
750 4430575 : (inner_scope_calls_eval_ && (IsConciseMethod(function_kind()) ||
751 245569 : IsAccessorFunction(function_kind()) ||
752 3934986 : IsClassConstructor(function_kind())));
753 : }
754 :
755 : bool calls_sloppy_eval() const {
756 : // TODO(delphick): Calculate this when setting and change the name of
757 : // scope_calls_eval_.
758 22570975 : return !is_script_scope() && scope_calls_eval_ &&
759 : is_sloppy(language_mode());
760 : }
761 :
762 12247967 : bool was_lazily_parsed() const { return was_lazily_parsed_; }
763 :
764 : Variable* LookupInModule(const AstRawString* name) {
765 : DCHECK(is_module_scope());
766 140 : Variable* var = variables_.Lookup(name);
767 : DCHECK_NOT_NULL(var);
768 : return var;
769 : }
770 :
771 : void DeserializeReceiver(AstValueFactory* ast_value_factory);
772 :
773 : #ifdef DEBUG
774 : void set_is_being_lazily_parsed(bool is_being_lazily_parsed) {
775 : is_being_lazily_parsed_ = is_being_lazily_parsed;
776 : }
777 : bool is_being_lazily_parsed() const { return is_being_lazily_parsed_; }
778 : #endif
779 : void set_zone(Zone* zone) {
780 : #ifdef DEBUG
781 : needs_migration_ = true;
782 : #endif
783 2625651 : zone_ = zone;
784 : }
785 :
786 : // ---------------------------------------------------------------------------
787 : // Illegal redeclaration support.
788 :
789 : // Check if the scope has conflicting var
790 : // declarations, i.e. a var declaration that has been hoisted from a nested
791 : // scope over a let binding of the same name.
792 : Declaration* CheckConflictingVarDeclarations();
793 :
794 : void set_has_checked_syntax(bool has_checked_syntax) {
795 177533 : has_checked_syntax_ = has_checked_syntax;
796 : }
797 2135794 : bool has_checked_syntax() const { return has_checked_syntax_; }
798 :
799 : bool ShouldEagerCompile() const {
800 9246962 : return force_eager_compilation_ || should_eager_compile_;
801 : }
802 :
803 : void set_should_eager_compile();
804 :
805 : void SetScriptScopeInfo(Handle<ScopeInfo> scope_info) {
806 : DCHECK(is_script_scope());
807 : DCHECK(scope_info_.is_null());
808 1021728 : scope_info_ = scope_info;
809 : }
810 :
811 3641107 : bool is_asm_module() const { return is_asm_module_; }
812 : void set_is_asm_module();
813 :
814 : bool should_ban_arguments() const {
815 : return IsClassMembersInitializerFunction(function_kind());
816 : }
817 :
818 : void DeclareThis(AstValueFactory* ast_value_factory);
819 : void DeclareArguments(AstValueFactory* ast_value_factory);
820 : void DeclareDefaultFunctionVariables(AstValueFactory* ast_value_factory);
821 :
822 : // Declare the function variable for a function literal. This variable
823 : // is in an intermediate scope between this function scope and the the
824 : // outer scope. Only possible for function scopes; at most one variable.
825 : //
826 : // This function needs to be called after all other variables have been
827 : // declared in the scope. It will add a variable for {name} to {variables_};
828 : // either the function variable itself, or a non-local in case the function
829 : // calls sloppy eval.
830 : Variable* DeclareFunctionVar(const AstRawString* name,
831 : Scope* cache = nullptr);
832 :
833 : // Declare some special internal variables which must be accessible to
834 : // Ignition without ScopeInfo.
835 : Variable* DeclareGeneratorObjectVar(const AstRawString* name);
836 :
837 : // Declare a parameter in this scope. When there are duplicated
838 : // parameters the rightmost one 'wins'. However, the implementation
839 : // expects all parameters to be declared and from left to right.
840 : Variable* DeclareParameter(const AstRawString* name, VariableMode mode,
841 : bool is_optional, bool is_rest,
842 : AstValueFactory* ast_value_factory, int position);
843 :
844 : // Makes sure that num_parameters_ and has_rest is correct for the preparser.
845 : void RecordParameter(bool is_rest);
846 :
847 : // Declare an implicit global variable in this scope which must be a
848 : // script scope. The variable was introduced (possibly from an inner
849 : // scope) by a reference to an unresolved variable with no intervening
850 : // with statements or eval calls.
851 : Variable* DeclareDynamicGlobal(const AstRawString* name,
852 : VariableKind variable_kind, Scope* cache);
853 :
854 : // The variable corresponding to the 'this' value.
855 : Variable* receiver() {
856 : DCHECK(has_this_declaration() || is_script_scope());
857 : DCHECK_NOT_NULL(receiver_);
858 : return receiver_;
859 : }
860 :
861 16195549 : bool has_this_declaration() const { return has_this_declaration_; }
862 :
863 : // The variable corresponding to the 'new.target' value.
864 : Variable* new_target_var() { return new_target_; }
865 :
866 : // The variable holding the function literal for named function
867 : // literals, or nullptr. Only valid for function scopes.
868 : Variable* function_var() const { return function_; }
869 :
870 : // The variable holding the JSGeneratorObject for generator, async
871 : // and async generator functions, and modules. Only valid for
872 : // function and module scopes.
873 : Variable* generator_object_var() const {
874 : DCHECK(is_function_scope() || is_module_scope());
875 : return GetRareVariable(RareVariable::kGeneratorObject);
876 : }
877 :
878 : // Parameters. The left-most parameter has index 0.
879 : // Only valid for function and module scopes.
880 : Variable* parameter(int index) const {
881 : DCHECK(is_function_scope() || is_module_scope());
882 : DCHECK(!is_being_lazily_parsed_);
883 2502491 : return params_[index];
884 : }
885 :
886 : // Returns the number of formal parameters, excluding a possible rest
887 : // parameter. Examples:
888 : // function foo(a, b) {} ==> 2
889 : // function foo(a, b, ...c) {} ==> 2
890 : // function foo(a, b, c = 1) {} ==> 3
891 : int num_parameters() const { return num_parameters_; }
892 :
893 : // The function's rest parameter (nullptr if there is none).
894 : Variable* rest_parameter() const {
895 2747161 : return has_rest_ ? params_[params_.length() - 1] : nullptr;
896 : }
897 :
898 2328552 : bool has_simple_parameters() const { return has_simple_parameters_; }
899 :
900 : // TODO(caitp): manage this state in a better way. PreParser must be able to
901 : // communicate that the scope is non-simple, without allocating any parameters
902 : // as the Parser does. This is necessary to ensure that TC39's proposed early
903 : // error can be reported consistently regardless of whether lazily parsed or
904 : // not.
905 : void SetHasNonSimpleParameters() {
906 : DCHECK(is_function_scope());
907 244123 : has_simple_parameters_ = false;
908 : }
909 :
910 56554 : void MakeParametersNonSimple() {
911 : SetHasNonSimpleParameters();
912 312866 : for (ZoneHashMap::Entry* p = variables_.Start(); p != nullptr;
913 : p = variables_.Next(p)) {
914 128156 : Variable* var = reinterpret_cast<Variable*>(p->value);
915 128156 : if (var->is_parameter()) var->MakeParameterNonSimple();
916 : }
917 56554 : }
918 :
919 : // Returns whether the arguments object aliases formal parameters.
920 : CreateArgumentsType GetArgumentsType() const {
921 : DCHECK(is_function_scope());
922 : DCHECK(!is_arrow_scope());
923 : DCHECK_NOT_NULL(arguments_);
924 : return is_sloppy(language_mode()) && has_simple_parameters()
925 : ? CreateArgumentsType::kMappedArguments
926 360764 : : CreateArgumentsType::kUnmappedArguments;
927 : }
928 :
929 : // The local variable 'arguments' if we need to allocate it; nullptr
930 : // otherwise.
931 : Variable* arguments() const {
932 : DCHECK_IMPLIES(is_arrow_scope(), arguments_ == nullptr);
933 : return arguments_;
934 : }
935 :
936 : Variable* this_function_var() const {
937 : Variable* this_function = GetRareVariable(RareVariable::kThisFunction);
938 :
939 : // This is only used in derived constructors atm.
940 : DCHECK(this_function == nullptr ||
941 : (is_function_scope() && (IsClassConstructor(function_kind()) ||
942 : IsConciseMethod(function_kind()) ||
943 : IsAccessorFunction(function_kind()))));
944 : return this_function;
945 : }
946 :
947 : // Adds a local variable in this scope's locals list. This is for adjusting
948 : // the scope of temporaries and do-expression vars when desugaring parameter
949 : // initializers.
950 : void AddLocal(Variable* var);
951 :
952 : void DeclareSloppyBlockFunction(
953 : SloppyBlockFunctionStatement* sloppy_block_function);
954 :
955 : // Go through sloppy_block_functions_ and hoist those (into this scope)
956 : // which should be hoisted.
957 : void HoistSloppyBlockFunctions(AstNodeFactory* factory);
958 :
959 : // Compute top scope and allocate variables. For lazy compilation the top
960 : // scope only contains the single lazily compiled function, so this
961 : // doesn't re-allocate variables repeatedly.
962 : //
963 : // Returns false if private names can not be resolved and
964 : // ParseInfo's pending_error_handler will be populated with an
965 : // error. Otherwise, returns true.
966 : V8_WARN_UNUSED_RESULT
967 : static bool Analyze(ParseInfo* info);
968 :
969 : // To be called during parsing. Do just enough scope analysis that we can
970 : // discard the Scope contents for lazily compiled functions. In particular,
971 : // this records variables which cannot be resolved inside the Scope (we don't
972 : // yet know what they will resolve to since the outer Scopes are incomplete)
973 : // and recreates them with the correct Zone with ast_node_factory.
974 : void AnalyzePartially(Parser* parser, AstNodeFactory* ast_node_factory);
975 :
976 : // Allocate ScopeInfos for top scope and any inner scopes that need them.
977 : // Does nothing if ScopeInfo is already allocated.
978 : static void AllocateScopeInfos(ParseInfo* info, Isolate* isolate);
979 :
980 : Handle<StringSet> CollectNonLocals(Isolate* isolate, ParseInfo* info,
981 : Handle<StringSet> non_locals);
982 :
983 : // Determine if we can use lazy compilation for this scope.
984 : bool AllowsLazyCompilation() const;
985 :
986 : // Make sure this closure and all outer closures are eagerly compiled.
987 : void ForceEagerCompilation() {
988 : DCHECK_EQ(this, GetClosureScope());
989 : DeclarationScope* s;
990 1854 : for (s = this; !s->is_script_scope();
991 : s = s->outer_scope()->GetClosureScope()) {
992 5 : s->force_eager_compilation_ = true;
993 : }
994 1844 : s->force_eager_compilation_ = true;
995 : }
996 :
997 : #ifdef DEBUG
998 : void PrintParameters();
999 : #endif
1000 :
1001 : V8_INLINE void AllocateLocals();
1002 : V8_INLINE void AllocateParameterLocals();
1003 : V8_INLINE void AllocateReceiver();
1004 :
1005 : void ResetAfterPreparsing(AstValueFactory* ast_value_factory, bool aborted);
1006 :
1007 284294 : bool is_skipped_function() const { return is_skipped_function_; }
1008 : void set_is_skipped_function(bool is_skipped_function) {
1009 60793 : is_skipped_function_ = is_skipped_function;
1010 : }
1011 :
1012 : bool has_inferred_function_name() const {
1013 : return has_inferred_function_name_;
1014 : }
1015 : void set_has_inferred_function_name(bool value) {
1016 : DCHECK(is_function_scope());
1017 1182910 : has_inferred_function_name_ = value;
1018 : }
1019 :
1020 : // Save data describing the context allocation of the variables in this scope
1021 : // and its subscopes (except scopes at the laziness boundary). The data is
1022 : // saved in produced_preparse_data_.
1023 : void SavePreparseDataForDeclarationScope(Parser* parser);
1024 :
1025 : void set_preparse_data_builder(PreparseDataBuilder* preparse_data_builder) {
1026 2681353 : preparse_data_builder_ = preparse_data_builder;
1027 : }
1028 :
1029 : PreparseDataBuilder* preparse_data_builder() const {
1030 : return preparse_data_builder_;
1031 : }
1032 :
1033 128921 : void set_has_this_reference() { has_this_reference_ = true; }
1034 3557 : bool has_this_reference() const { return has_this_reference_; }
1035 : void UsesThis() {
1036 : set_has_this_reference();
1037 102 : GetReceiverScope()->receiver()->ForceContextAllocation();
1038 : }
1039 :
1040 : private:
1041 : V8_INLINE void AllocateParameter(Variable* var, int index);
1042 :
1043 : // Resolve and fill in the allocation information for all variables
1044 : // in this scopes. Must be called *after* all scopes have been
1045 : // processed (parsed) to ensure that unresolved variables can be
1046 : // resolved properly.
1047 : //
1048 : // In the case of code compiled and run using 'eval', the context
1049 : // parameter is the context in which eval was called. In all other
1050 : // cases the context parameter is an empty handle.
1051 : //
1052 : // Returns false if private names can not be resolved.
1053 : bool AllocateVariables(ParseInfo* info);
1054 :
1055 : void SetDefaults();
1056 :
1057 : bool has_simple_parameters_ : 1;
1058 : // This scope contains an "use asm" annotation.
1059 : bool is_asm_module_ : 1;
1060 : bool force_eager_compilation_ : 1;
1061 : // This function scope has a rest parameter.
1062 : bool has_rest_ : 1;
1063 : // This scope has a parameter called "arguments".
1064 : bool has_arguments_parameter_ : 1;
1065 : // This scope uses "super" property ('super.foo').
1066 : bool scope_uses_super_property_ : 1;
1067 : bool should_eager_compile_ : 1;
1068 : // Set to true after we have finished lazy parsing the scope.
1069 : bool was_lazily_parsed_ : 1;
1070 : #if DEBUG
1071 : bool is_being_lazily_parsed_ : 1;
1072 : #endif
1073 : bool is_skipped_function_ : 1;
1074 : bool has_inferred_function_name_ : 1;
1075 : bool has_checked_syntax_ : 1;
1076 : bool has_this_reference_ : 1;
1077 : bool has_this_declaration_ : 1;
1078 :
1079 : // If the scope is a function scope, this is the function kind.
1080 : const FunctionKind function_kind_;
1081 :
1082 : int num_parameters_ = 0;
1083 :
1084 : // Parameter list in source order.
1085 : ZonePtrList<Variable> params_;
1086 : // Map of function names to lists of functions defined in sloppy blocks
1087 : base::ThreadedList<SloppyBlockFunctionStatement> sloppy_block_functions_;
1088 : // Convenience variable.
1089 : Variable* receiver_;
1090 : // Function variable, if any; function scopes only.
1091 : Variable* function_;
1092 : // new.target variable, function scopes only.
1093 : Variable* new_target_;
1094 : // Convenience variable; function scopes only.
1095 : Variable* arguments_;
1096 :
1097 : // For producing the scope allocation data during preparsing.
1098 : PreparseDataBuilder* preparse_data_builder_;
1099 :
1100 1075694 : struct RareData : public ZoneObject {
1101 : // Convenience variable; Subclass constructor only
1102 : Variable* this_function = nullptr;
1103 :
1104 : // Generator object, if any; generator function scopes and module scopes
1105 : // only.
1106 : Variable* generator_object = nullptr;
1107 : };
1108 :
1109 : enum class RareVariable {
1110 : kThisFunction = offsetof(RareData, this_function),
1111 : kGeneratorObject = offsetof(RareData, generator_object),
1112 : };
1113 :
1114 : V8_INLINE RareData* EnsureRareData() {
1115 1087967 : if (rare_data_ == nullptr) {
1116 2151390 : rare_data_ = new (zone_) RareData;
1117 : }
1118 1087965 : return rare_data_;
1119 : }
1120 :
1121 : V8_INLINE Variable* GetRareVariable(RareVariable id) const {
1122 2322600 : if (rare_data_ == nullptr) return nullptr;
1123 : return *reinterpret_cast<Variable**>(
1124 351475 : reinterpret_cast<uint8_t*>(rare_data_) + static_cast<ptrdiff_t>(id));
1125 : }
1126 :
1127 : // Set `var` to null if it's non-null and Predicate (Variable*) -> bool
1128 : // returns true.
1129 : template <typename Predicate>
1130 : V8_INLINE void NullifyRareVariableIf(RareVariable id, Predicate predicate) {
1131 2722415 : if (V8_LIKELY(rare_data_ == nullptr)) return;
1132 : Variable** var = reinterpret_cast<Variable**>(
1133 : reinterpret_cast<uint8_t*>(rare_data_) + static_cast<ptrdiff_t>(id));
1134 366401 : if (*var && predicate(*var)) *var = nullptr;
1135 : }
1136 :
1137 : RareData* rare_data_ = nullptr;
1138 : };
1139 :
1140 3117887 : Scope::Snapshot::Snapshot(Scope* scope)
1141 3117887 : : outer_scope_and_calls_eval_(scope, scope->scope_calls_eval_),
1142 3117887 : top_inner_scope_(scope->inner_scope_),
1143 : top_unresolved_(scope->unresolved_list_.end()),
1144 3117887 : top_local_(scope->GetClosureScope()->locals_.end()) {
1145 : // Reset in order to record eval calls during this Snapshot's lifetime.
1146 3117887 : outer_scope_and_calls_eval_.GetPointer()->scope_calls_eval_ = false;
1147 3117887 : }
1148 :
1149 : class ModuleScope final : public DeclarationScope {
1150 : public:
1151 : ModuleScope(DeclarationScope* script_scope, AstValueFactory* avfactory);
1152 :
1153 : // Deserialization. Does not restore the module descriptor.
1154 : ModuleScope(Isolate* isolate, Handle<ScopeInfo> scope_info,
1155 : AstValueFactory* avfactory);
1156 :
1157 : // Returns nullptr in a deserialized scope.
1158 : ModuleDescriptor* module() const { return module_descriptor_; }
1159 :
1160 : // Set MODULE as VariableLocation for all variables that will live in a
1161 : // module's export table.
1162 : void AllocateModuleVariables();
1163 :
1164 : private:
1165 : ModuleDescriptor* const module_descriptor_;
1166 : };
1167 :
1168 : class V8_EXPORT_PRIVATE ClassScope : public Scope {
1169 : public:
1170 : ClassScope(Zone* zone, Scope* outer_scope);
1171 : // Deserialization.
1172 : ClassScope(Zone* zone, Handle<ScopeInfo> scope_info);
1173 :
1174 : // Declare a private name in the private name map and add it to the
1175 : // local variables of this scope.
1176 : Variable* DeclarePrivateName(const AstRawString* name, bool* was_added);
1177 :
1178 : void AddUnresolvedPrivateName(VariableProxy* proxy);
1179 :
1180 : // Try resolving all unresolved private names found in the current scope.
1181 : // Called from DeclarationScope::AllocateVariables() when reparsing a
1182 : // method to generate code or when eval() is called to access private names.
1183 : // If there are any private names that cannot be resolved, returns false.
1184 : V8_WARN_UNUSED_RESULT bool ResolvePrivateNames(ParseInfo* info);
1185 :
1186 : // Called after the entire class literal is parsed.
1187 : // - If we are certain a private name cannot be resolve, return that
1188 : // variable proxy.
1189 : // - If we find the private name in the scope chain, return nullptr.
1190 : // If the name is found in the current class scope, resolve it
1191 : // immediately.
1192 : // - If we are not sure if the private name can be resolved or not yet,
1193 : // return nullptr.
1194 : VariableProxy* ResolvePrivateNamesPartially();
1195 :
1196 : // Get the current tail of unresolved private names to be used to
1197 : // reset the tail.
1198 : UnresolvedList::Iterator GetUnresolvedPrivateNameTail();
1199 :
1200 : // Reset the tail of unresolved private names, discard everything
1201 : // between the tail passed into this method and the current tail.
1202 : void ResetUnresolvedPrivateNameTail(UnresolvedList::Iterator tail);
1203 :
1204 : // Migrate private names added between the tail passed into this method
1205 : // and the current tail.
1206 : void MigrateUnresolvedPrivateNameTail(AstNodeFactory* ast_node_factory,
1207 : UnresolvedList::Iterator tail);
1208 :
1209 : private:
1210 : friend class Scope;
1211 : // Find the private name declared in the private name map first,
1212 : // if it cannot be found there, try scope info if there is any.
1213 : // Returns nullptr if it cannot be found.
1214 : Variable* LookupPrivateName(VariableProxy* proxy);
1215 : // Lookup a private name from the local private name map of the current
1216 : // scope.
1217 : Variable* LookupLocalPrivateName(const AstRawString* name);
1218 : // Lookup a private name from the scope info of the current scope.
1219 : Variable* LookupPrivateNameInScopeInfo(const AstRawString* name);
1220 :
1221 : struct RareData : public ZoneObject {
1222 8050 : explicit RareData(Zone* zone) : private_name_map(zone) {}
1223 : UnresolvedList unresolved_private_names;
1224 : VariableMap private_name_map;
1225 : };
1226 :
1227 : V8_INLINE RareData* EnsureRareData() {
1228 25667 : if (rare_data_ == nullptr) {
1229 39125 : rare_data_ = new (zone_) RareData(zone_);
1230 : }
1231 25667 : return rare_data_;
1232 : }
1233 :
1234 : RareData* rare_data_ = nullptr;
1235 : };
1236 :
1237 : } // namespace internal
1238 : } // namespace v8
1239 :
1240 : #endif // V8_AST_SCOPES_H_
|