V8 API Reference, 7.2.502.16 (for Deno 0.2.4)
scopes.cc
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 #include "src/ast/scopes.h"
6 
7 #include <set>
8 
9 #include "src/accessors.h"
10 #include "src/ast/ast.h"
11 #include "src/base/optional.h"
12 #include "src/bootstrapper.h"
13 #include "src/counters.h"
14 #include "src/message-template.h"
15 #include "src/objects-inl.h"
16 #include "src/objects/module-inl.h"
17 #include "src/objects/scope-info.h"
18 #include "src/parsing/parse-info.h"
19 #include "src/parsing/preparsed-scope-data.h"
20 #include "src/zone/zone-list-inl.h"
21 
22 namespace v8 {
23 namespace internal {
24 
25 namespace {
26 bool IsLexical(Variable* variable) {
27  if (variable == Scope::kDummyPreParserLexicalVariable) return true;
28  if (variable == Scope::kDummyPreParserVariable) return false;
29  return IsLexicalVariableMode(variable->mode());
30 }
31 } // namespace
32 
33 // ----------------------------------------------------------------------------
34 // Implementation of LocalsMap
35 //
36 // Note: We are storing the handle locations as key values in the hash map.
37 // When inserting a new variable via Declare(), we rely on the fact that
38 // the handle location remains alive for the duration of that variable
39 // use. Because a Variable holding a handle with the same location exists
40 // this is ensured.
41 
42 VariableMap::VariableMap(Zone* zone)
43  : ZoneHashMap(8, ZoneAllocationPolicy(zone)) {}
44 
45 Variable* VariableMap::Declare(Zone* zone, Scope* scope,
46  const AstRawString* name, VariableMode mode,
47  VariableKind kind,
48  InitializationFlag initialization_flag,
49  MaybeAssignedFlag maybe_assigned_flag,
50  base::ThreadedList<Variable>* variable_list) {
51  // AstRawStrings are unambiguous, i.e., the same string is always represented
52  // by the same AstRawString*.
53  // FIXME(marja): fix the type of Lookup.
54  Entry* p =
55  ZoneHashMap::LookupOrInsert(const_cast<AstRawString*>(name), name->Hash(),
56  ZoneAllocationPolicy(zone));
57  if (p->value == nullptr) {
58  // The variable has not been declared yet -> insert it.
59  DCHECK_EQ(name, p->key);
60  Variable* variable = new (zone) Variable(
61  scope, name, mode, kind, initialization_flag, maybe_assigned_flag);
62  if (variable_list) variable_list->Add(variable);
63  p->value = variable;
64  }
65  return reinterpret_cast<Variable*>(p->value);
66 }
67 
68 Variable* VariableMap::DeclareName(Zone* zone, const AstRawString* name,
69  VariableMode mode) {
70  Entry* p =
71  ZoneHashMap::LookupOrInsert(const_cast<AstRawString*>(name), name->Hash(),
72  ZoneAllocationPolicy(zone));
73  if (p->value == nullptr) {
74  // The variable has not been declared yet -> insert it.
75  DCHECK_EQ(name, p->key);
76  p->value = mode == VariableMode::kVar
77  ? Scope::kDummyPreParserVariable
78  : Scope::kDummyPreParserLexicalVariable;
79  }
80  return reinterpret_cast<Variable*>(p->value);
81 }
82 
83 void VariableMap::Remove(Variable* var) {
84  const AstRawString* name = var->raw_name();
85  ZoneHashMap::Remove(const_cast<AstRawString*>(name), name->Hash());
86 }
87 
88 void VariableMap::Add(Zone* zone, Variable* var) {
89  const AstRawString* name = var->raw_name();
90  Entry* p =
91  ZoneHashMap::LookupOrInsert(const_cast<AstRawString*>(name), name->Hash(),
92  ZoneAllocationPolicy(zone));
93  DCHECK_NULL(p->value);
94  DCHECK_EQ(name, p->key);
95  p->value = var;
96 }
97 
98 Variable* VariableMap::Lookup(const AstRawString* name) {
99  Entry* p = ZoneHashMap::Lookup(const_cast<AstRawString*>(name), name->Hash());
100  if (p != nullptr) {
101  DCHECK(reinterpret_cast<const AstRawString*>(p->key) == name);
102  DCHECK_NOT_NULL(p->value);
103  return reinterpret_cast<Variable*>(p->value);
104  }
105  return nullptr;
106 }
107 
108 void SloppyBlockFunctionMap::Delegate::set_statement(Statement* statement) {
109  if (statement_ != nullptr) {
110  statement_->set_statement(statement);
111  }
112 }
113 
114 SloppyBlockFunctionMap::SloppyBlockFunctionMap(Zone* zone)
115  : ZoneHashMap(8, ZoneAllocationPolicy(zone)), count_(0) {}
116 
117 void SloppyBlockFunctionMap::Declare(Zone* zone, const AstRawString* name,
118  Scope* scope,
119  SloppyBlockFunctionStatement* statement) {
120  auto* delegate = new (zone) Delegate(scope, statement, count_++);
121  // AstRawStrings are unambiguous, i.e., the same string is always represented
122  // by the same AstRawString*.
123  Entry* p =
124  ZoneHashMap::LookupOrInsert(const_cast<AstRawString*>(name), name->Hash(),
125  ZoneAllocationPolicy(zone));
126  delegate->set_next(static_cast<SloppyBlockFunctionMap::Delegate*>(p->value));
127  p->value = delegate;
128 }
129 
130 // ----------------------------------------------------------------------------
131 // Implementation of Scope
132 
133 Scope::Scope(Zone* zone)
134  : zone_(zone),
135  outer_scope_(nullptr),
136  variables_(zone),
137  scope_type_(SCRIPT_SCOPE) {
138  SetDefaults();
139 }
140 
141 Scope::Scope(Zone* zone, Scope* outer_scope, ScopeType scope_type)
142  : zone_(zone),
143  outer_scope_(outer_scope),
144  variables_(zone),
145  scope_type_(scope_type) {
146  DCHECK_NE(SCRIPT_SCOPE, scope_type);
147  SetDefaults();
148  set_language_mode(outer_scope->language_mode());
149  outer_scope_->AddInnerScope(this);
150 }
151 
152 DeclarationScope::DeclarationScope(Zone* zone,
153  AstValueFactory* ast_value_factory)
154  : Scope(zone), function_kind_(kNormalFunction), params_(4, zone) {
155  DCHECK_EQ(scope_type_, SCRIPT_SCOPE);
156  SetDefaults();
157 
158  // Make sure that if we don't find the global 'this', it won't be declared as
159  // a regular dynamic global by predeclaring it with the right variable kind.
160  DeclareDynamicGlobal(ast_value_factory->this_string(), THIS_VARIABLE, this);
161 }
162 
163 DeclarationScope::DeclarationScope(Zone* zone, Scope* outer_scope,
164  ScopeType scope_type,
165  FunctionKind function_kind)
166  : Scope(zone, outer_scope, scope_type),
167  function_kind_(function_kind),
168  params_(4, zone) {
169  DCHECK_NE(scope_type, SCRIPT_SCOPE);
170  SetDefaults();
171 }
172 
173 bool DeclarationScope::IsDeclaredParameter(const AstRawString* name) {
174  // If IsSimpleParameterList is false, duplicate parameters are not allowed,
175  // however `arguments` may be allowed if function is not strict code. Thus,
176  // the assumptions explained above do not hold.
177  return params_.Contains(variables_.Lookup(name));
178 }
179 
180 ModuleScope::ModuleScope(DeclarationScope* script_scope,
181  AstValueFactory* ast_value_factory)
182  : DeclarationScope(ast_value_factory->zone(), script_scope, MODULE_SCOPE,
183  kModule) {
184  Zone* zone = ast_value_factory->zone();
185  module_descriptor_ = new (zone) ModuleDescriptor(zone);
186  set_language_mode(LanguageMode::kStrict);
187  DeclareThis(ast_value_factory);
188 }
189 
190 ModuleScope::ModuleScope(Isolate* isolate, Handle<ScopeInfo> scope_info,
191  AstValueFactory* avfactory)
192  : DeclarationScope(avfactory->zone(), MODULE_SCOPE, scope_info) {
193  Zone* zone = avfactory->zone();
194  Handle<ModuleInfo> module_info(scope_info->ModuleDescriptorInfo(), isolate);
195 
196  set_language_mode(LanguageMode::kStrict);
197  module_descriptor_ = new (zone) ModuleDescriptor(zone);
198 
199  // Deserialize special exports.
200  Handle<FixedArray> special_exports(module_info->special_exports(), isolate);
201  for (int i = 0, n = special_exports->length(); i < n; ++i) {
202  Handle<ModuleInfoEntry> serialized_entry(
203  ModuleInfoEntry::cast(special_exports->get(i)), isolate);
204  module_descriptor_->AddSpecialExport(
205  ModuleDescriptor::Entry::Deserialize(isolate, avfactory,
206  serialized_entry),
207  avfactory->zone());
208  }
209 
210  // Deserialize regular exports.
211  module_descriptor_->DeserializeRegularExports(isolate, avfactory,
212  module_info);
213 
214  // Deserialize namespace imports.
215  Handle<FixedArray> namespace_imports(module_info->namespace_imports(),
216  isolate);
217  for (int i = 0, n = namespace_imports->length(); i < n; ++i) {
218  Handle<ModuleInfoEntry> serialized_entry(
219  ModuleInfoEntry::cast(namespace_imports->get(i)), isolate);
220  module_descriptor_->AddNamespaceImport(
221  ModuleDescriptor::Entry::Deserialize(isolate, avfactory,
222  serialized_entry),
223  avfactory->zone());
224  }
225 
226  // Deserialize regular imports.
227  Handle<FixedArray> regular_imports(module_info->regular_imports(), isolate);
228  for (int i = 0, n = regular_imports->length(); i < n; ++i) {
229  Handle<ModuleInfoEntry> serialized_entry(
230  ModuleInfoEntry::cast(regular_imports->get(i)), isolate);
231  module_descriptor_->AddRegularImport(ModuleDescriptor::Entry::Deserialize(
232  isolate, avfactory, serialized_entry));
233  }
234 }
235 
236 Scope::Scope(Zone* zone, ScopeType scope_type, Handle<ScopeInfo> scope_info)
237  : zone_(zone),
238  outer_scope_(nullptr),
239  variables_(zone),
240  scope_info_(scope_info),
241  scope_type_(scope_type) {
242  DCHECK(!scope_info.is_null());
243  SetDefaults();
244 #ifdef DEBUG
245  already_resolved_ = true;
246 #endif
247  if (scope_info->CallsSloppyEval()) scope_calls_eval_ = true;
248  set_language_mode(scope_info->language_mode());
249  num_heap_slots_ = scope_info->ContextLength();
250  DCHECK_LE(Context::MIN_CONTEXT_SLOTS, num_heap_slots_);
251  // We don't really need to use the preparsed scope data; this is just to
252  // shorten the recursion in SetMustUsePreParsedScopeData.
253  must_use_preparsed_scope_data_ = true;
254 }
255 
256 DeclarationScope::DeclarationScope(Zone* zone, ScopeType scope_type,
257  Handle<ScopeInfo> scope_info)
258  : Scope(zone, scope_type, scope_info),
259  function_kind_(scope_info->function_kind()),
260  params_(0, zone) {
261  DCHECK_NE(scope_type, SCRIPT_SCOPE);
262  SetDefaults();
263 }
264 
265 Scope::Scope(Zone* zone, const AstRawString* catch_variable_name,
266  MaybeAssignedFlag maybe_assigned, Handle<ScopeInfo> scope_info)
267  : zone_(zone),
268  outer_scope_(nullptr),
269  variables_(zone),
270  scope_info_(scope_info),
271  scope_type_(CATCH_SCOPE) {
272  SetDefaults();
273 #ifdef DEBUG
274  already_resolved_ = true;
275 #endif
276  // Cache the catch variable, even though it's also available via the
277  // scope_info, as the parser expects that a catch scope always has the catch
278  // variable as first and only variable.
279  Variable* variable =
280  Declare(zone, catch_variable_name, VariableMode::kVar, NORMAL_VARIABLE,
281  kCreatedInitialized, maybe_assigned);
282  AllocateHeapSlot(variable);
283 }
284 
285 void DeclarationScope::SetDefaults() {
286  is_declaration_scope_ = true;
287  has_simple_parameters_ = true;
288  asm_module_ = false;
289  force_eager_compilation_ = false;
290  has_arguments_parameter_ = false;
291  scope_uses_super_property_ = false;
292  has_rest_ = false;
293  sloppy_block_function_map_ = nullptr;
294  receiver_ = nullptr;
295  new_target_ = nullptr;
296  function_ = nullptr;
297  arguments_ = nullptr;
298  rare_data_ = nullptr;
299  should_eager_compile_ = false;
300  was_lazily_parsed_ = false;
301  is_skipped_function_ = false;
302  preparsed_scope_data_builder_ = nullptr;
303 #ifdef DEBUG
304  DeclarationScope* outer_declaration_scope =
305  outer_scope_ ? outer_scope_->GetDeclarationScope() : nullptr;
306  is_being_lazily_parsed_ =
307  outer_declaration_scope ? outer_declaration_scope->is_being_lazily_parsed_
308  : false;
309 #endif
310 }
311 
312 void Scope::SetDefaults() {
313 #ifdef DEBUG
314  scope_name_ = nullptr;
315  already_resolved_ = false;
316  needs_migration_ = false;
317 #endif
318  inner_scope_ = nullptr;
319  sibling_ = nullptr;
320  unresolved_list_.Clear();
321 
322  start_position_ = kNoSourcePosition;
323  end_position_ = kNoSourcePosition;
324 
325  num_stack_slots_ = 0;
326  num_heap_slots_ = Context::MIN_CONTEXT_SLOTS;
327 
328  set_language_mode(LanguageMode::kSloppy);
329 
330  scope_calls_eval_ = false;
331  scope_nonlinear_ = false;
332  is_hidden_ = false;
333  is_debug_evaluate_scope_ = false;
334 
335  inner_scope_calls_eval_ = false;
336  force_context_allocation_ = false;
337  force_context_allocation_for_parameters_ = false;
338 
339  is_declaration_scope_ = false;
340 
341  must_use_preparsed_scope_data_ = false;
342 }
343 
344 bool Scope::HasSimpleParameters() {
345  DeclarationScope* scope = GetClosureScope();
346  return !scope->is_function_scope() || scope->has_simple_parameters();
347 }
348 
349 bool DeclarationScope::ShouldEagerCompile() const {
350  return force_eager_compilation_ || should_eager_compile_;
351 }
352 
353 void DeclarationScope::set_should_eager_compile() {
354  should_eager_compile_ = !was_lazily_parsed_;
355 }
356 
357 void DeclarationScope::set_asm_module() {
358  asm_module_ = true;
359 }
360 
361 bool Scope::IsAsmModule() const {
362  return is_function_scope() && AsDeclarationScope()->asm_module();
363 }
364 
365 bool Scope::ContainsAsmModule() const {
366  if (IsAsmModule()) return true;
367 
368  // Check inner scopes recursively
369  for (Scope* scope = inner_scope_; scope != nullptr; scope = scope->sibling_) {
370  // Don't check inner functions which won't be eagerly compiled.
371  if (!scope->is_function_scope() ||
372  scope->AsDeclarationScope()->ShouldEagerCompile()) {
373  if (scope->ContainsAsmModule()) return true;
374  }
375  }
376 
377  return false;
378 }
379 
380 Scope* Scope::DeserializeScopeChain(Isolate* isolate, Zone* zone,
381  ScopeInfo scope_info,
382  DeclarationScope* script_scope,
383  AstValueFactory* ast_value_factory,
384  DeserializationMode deserialization_mode) {
385  // Reconstruct the outer scope chain from a closure's context chain.
386  Scope* current_scope = nullptr;
387  Scope* innermost_scope = nullptr;
388  Scope* outer_scope = nullptr;
389  while (!scope_info.is_null()) {
390  if (scope_info->scope_type() == WITH_SCOPE) {
391  // For scope analysis, debug-evaluate is equivalent to a with scope.
392  outer_scope =
393  new (zone) Scope(zone, WITH_SCOPE, handle(scope_info, isolate));
394 
395  // TODO(yangguo): Remove once debug-evaluate properly keeps track of the
396  // function scope in which we are evaluating.
397  if (scope_info->IsDebugEvaluateScope()) {
398  outer_scope->set_is_debug_evaluate_scope();
399  }
400  } else if (scope_info->scope_type() == SCRIPT_SCOPE) {
401  // If we reach a script scope, it's the outermost scope. Install the
402  // scope info of this script context onto the existing script scope to
403  // avoid nesting script scopes.
404  if (deserialization_mode == DeserializationMode::kIncludingVariables) {
405  script_scope->SetScriptScopeInfo(handle(scope_info, isolate));
406  }
407  DCHECK(!scope_info->HasOuterScopeInfo());
408  break;
409  } else if (scope_info->scope_type() == FUNCTION_SCOPE) {
410  outer_scope = new (zone)
411  DeclarationScope(zone, FUNCTION_SCOPE, handle(scope_info, isolate));
412  if (scope_info->IsAsmModule())
413  outer_scope->AsDeclarationScope()->set_asm_module();
414  } else if (scope_info->scope_type() == EVAL_SCOPE) {
415  outer_scope = new (zone)
416  DeclarationScope(zone, EVAL_SCOPE, handle(scope_info, isolate));
417  } else if (scope_info->scope_type() == BLOCK_SCOPE) {
418  if (scope_info->is_declaration_scope()) {
419  outer_scope = new (zone)
420  DeclarationScope(zone, BLOCK_SCOPE, handle(scope_info, isolate));
421  } else {
422  outer_scope =
423  new (zone) Scope(zone, BLOCK_SCOPE, handle(scope_info, isolate));
424  }
425  } else if (scope_info->scope_type() == MODULE_SCOPE) {
426  outer_scope = new (zone)
427  ModuleScope(isolate, handle(scope_info, isolate), ast_value_factory);
428  } else {
429  DCHECK_EQ(scope_info->scope_type(), CATCH_SCOPE);
430  DCHECK_EQ(scope_info->ContextLocalCount(), 1);
431  DCHECK_EQ(scope_info->ContextLocalMode(0), VariableMode::kVar);
432  DCHECK_EQ(scope_info->ContextLocalInitFlag(0), kCreatedInitialized);
433  String name = scope_info->ContextLocalName(0);
434  MaybeAssignedFlag maybe_assigned =
435  scope_info->ContextLocalMaybeAssignedFlag(0);
436  outer_scope = new (zone)
437  Scope(zone, ast_value_factory->GetString(handle(name, isolate)),
438  maybe_assigned, handle(scope_info, isolate));
439  }
440  if (deserialization_mode == DeserializationMode::kScopesOnly) {
441  outer_scope->scope_info_ = Handle<ScopeInfo>::null();
442  }
443  if (current_scope != nullptr) {
444  outer_scope->AddInnerScope(current_scope);
445  }
446  current_scope = outer_scope;
447  if (innermost_scope == nullptr) innermost_scope = current_scope;
448  scope_info = scope_info->HasOuterScopeInfo() ? scope_info->OuterScopeInfo()
449  : ScopeInfo();
450  }
451 
452  if (deserialization_mode == DeserializationMode::kIncludingVariables &&
453  script_scope->scope_info_.is_null()) {
454  Handle<ScriptContextTable> table(
455  isolate->native_context()->script_context_table(), isolate);
456  Handle<Context> first = ScriptContextTable::GetContext(isolate, table, 0);
457  Handle<ScopeInfo> scope_info(first->scope_info(), isolate);
458  script_scope->SetScriptScopeInfo(scope_info);
459  }
460 
461  if (innermost_scope == nullptr) return script_scope;
462  script_scope->AddInnerScope(current_scope);
463  return innermost_scope;
464 }
465 
466 DeclarationScope* Scope::AsDeclarationScope() {
467  DCHECK(is_declaration_scope());
468  return static_cast<DeclarationScope*>(this);
469 }
470 
471 const DeclarationScope* Scope::AsDeclarationScope() const {
472  DCHECK(is_declaration_scope());
473  return static_cast<const DeclarationScope*>(this);
474 }
475 
476 ModuleScope* Scope::AsModuleScope() {
477  DCHECK(is_module_scope());
478  return static_cast<ModuleScope*>(this);
479 }
480 
481 const ModuleScope* Scope::AsModuleScope() const {
482  DCHECK(is_module_scope());
483  return static_cast<const ModuleScope*>(this);
484 }
485 
486 int Scope::num_parameters() const {
487  return is_declaration_scope() ? AsDeclarationScope()->num_parameters() : 0;
488 }
489 
490 void DeclarationScope::DeclareSloppyBlockFunction(
491  const AstRawString* name, Scope* scope,
492  SloppyBlockFunctionStatement* statement) {
493  if (sloppy_block_function_map_ == nullptr) {
494  sloppy_block_function_map_ =
495  new (zone()->New(sizeof(SloppyBlockFunctionMap)))
496  SloppyBlockFunctionMap(zone());
497  }
498  sloppy_block_function_map_->Declare(zone(), name, scope, statement);
499 }
500 
501 void DeclarationScope::HoistSloppyBlockFunctions(AstNodeFactory* factory) {
502  DCHECK(is_sloppy(language_mode()));
503  DCHECK(is_function_scope() || is_eval_scope() || is_script_scope() ||
504  (is_block_scope() && outer_scope()->is_function_scope()));
505  DCHECK(HasSimpleParameters() || is_block_scope() || is_being_lazily_parsed_);
506  DCHECK_EQ(factory == nullptr, is_being_lazily_parsed_);
507 
508  SloppyBlockFunctionMap* map = sloppy_block_function_map();
509  if (map == nullptr) return;
510 
511  const bool has_simple_parameters = HasSimpleParameters();
512 
513  // The declarations need to be added in the order they were seen,
514  // so accumulate declared names sorted by index.
515  ZoneMap<int, const AstRawString*> names_to_declare(zone());
516 
517  // For each variable which is used as a function declaration in a sloppy
518  // block,
519  for (ZoneHashMap::Entry* p = map->Start(); p != nullptr; p = map->Next(p)) {
520  const AstRawString* name = static_cast<AstRawString*>(p->key);
521 
522  // If the variable wouldn't conflict with a lexical declaration
523  // or parameter,
524 
525  // Check if there's a conflict with a parameter.
526  // This depends on the fact that functions always have a scope solely to
527  // hold complex parameters, and the names local to that scope are
528  // precisely the names of the parameters. IsDeclaredParameter(name) does
529  // not hold for names declared by complex parameters, nor are those
530  // bindings necessarily declared lexically, so we have to check for them
531  // explicitly. On the other hand, if there are not complex parameters,
532  // it is sufficient to just check IsDeclaredParameter.
533  if (!has_simple_parameters) {
534  if (outer_scope_->LookupLocal(name) != nullptr) {
535  continue;
536  }
537  } else {
538  if (IsDeclaredParameter(name)) {
539  continue;
540  }
541  }
542 
543  bool declaration_queued = false;
544 
545  // Write in assignments to var for each block-scoped function declaration
546  auto delegates = static_cast<SloppyBlockFunctionMap::Delegate*>(p->value);
547 
548  DeclarationScope* decl_scope = this;
549  while (decl_scope->is_eval_scope()) {
550  decl_scope = decl_scope->outer_scope()->GetDeclarationScope();
551  }
552  Scope* outer_scope = decl_scope->outer_scope();
553 
554  for (SloppyBlockFunctionMap::Delegate* delegate = delegates;
555  delegate != nullptr; delegate = delegate->next()) {
556  // Check if there's a conflict with a lexical declaration
557  Scope* query_scope = delegate->scope()->outer_scope();
558  Variable* var = nullptr;
559  bool should_hoist = true;
560 
561  // Note that we perform this loop for each delegate named 'name',
562  // which may duplicate work if those delegates share scopes.
563  // It is not sufficient to just do a Lookup on query_scope: for
564  // example, that does not prevent hoisting of the function in
565  // `{ let e; try {} catch (e) { function e(){} } }`
566  do {
567  var = query_scope->LookupInScopeOrScopeInfo(name);
568  if (var != nullptr && IsLexical(var)) {
569  should_hoist = false;
570  break;
571  }
572  query_scope = query_scope->outer_scope();
573  } while (query_scope != outer_scope);
574 
575  if (!should_hoist) continue;
576 
577  if (!declaration_queued) {
578  declaration_queued = true;
579  names_to_declare.insert({delegate->index(), name});
580  }
581 
582  if (factory) {
583  DCHECK(!is_being_lazily_parsed_);
584  Assignment* assignment = factory->NewAssignment(
585  Token::ASSIGN, NewUnresolved(factory, name),
586  delegate->scope()->NewUnresolved(factory, name), kNoSourcePosition);
587  assignment->set_lookup_hoisting_mode(LookupHoistingMode::kLegacySloppy);
588  Statement* statement =
589  factory->NewExpressionStatement(assignment, kNoSourcePosition);
590  delegate->set_statement(statement);
591  }
592  }
593  }
594 
595  if (names_to_declare.empty()) return;
596 
597  for (const auto& index_and_name : names_to_declare) {
598  const AstRawString* name = index_and_name.second;
599  if (factory) {
600  DCHECK(!is_being_lazily_parsed_);
601  VariableProxy* proxy = factory->NewVariableProxy(name, NORMAL_VARIABLE);
602  auto declaration =
603  factory->NewVariableDeclaration(proxy, kNoSourcePosition);
604  // Based on the preceding checks, it doesn't matter what we pass as
605  // sloppy_mode_block_scope_function_redefinition.
606  bool ok = true;
607  DeclareVariable(declaration, VariableMode::kVar,
608  Variable::DefaultInitializationFlag(VariableMode::kVar),
609  nullptr, &ok);
610  DCHECK(ok);
611  } else {
612  DCHECK(is_being_lazily_parsed_);
613  Variable* var = DeclareVariableName(name, VariableMode::kVar);
614  if (var != kDummyPreParserVariable &&
615  var != kDummyPreParserLexicalVariable) {
616  var->set_maybe_assigned();
617  }
618  }
619  }
620 }
621 
622 void DeclarationScope::AttachOuterScopeInfo(ParseInfo* info, Isolate* isolate) {
623  DCHECK(scope_info_.is_null());
624  Handle<ScopeInfo> outer_scope_info;
625  if (info->maybe_outer_scope_info().ToHandle(&outer_scope_info)) {
626  // If we have a scope info we will potentially need to lookup variable names
627  // on the scope info as internalized strings, so make sure ast_value_factory
628  // is internalized.
629  info->ast_value_factory()->Internalize(isolate);
630  if (outer_scope()) {
631  DeclarationScope* script_scope = new (info->zone())
632  DeclarationScope(info->zone(), info->ast_value_factory());
633  info->set_script_scope(script_scope);
634  ReplaceOuterScope(Scope::DeserializeScopeChain(
635  isolate, info->zone(), *outer_scope_info, script_scope,
636  info->ast_value_factory(),
637  Scope::DeserializationMode::kIncludingVariables));
638  } else {
639  DCHECK_EQ(outer_scope_info->scope_type(), SCRIPT_SCOPE);
640  SetScriptScopeInfo(outer_scope_info);
641  }
642  }
643 }
644 
645 bool DeclarationScope::Analyze(ParseInfo* info) {
646  RuntimeCallTimerScope runtimeTimer(
647  info->runtime_call_stats(),
648  info->on_background_thread()
649  ? RuntimeCallCounterId::kCompileBackgroundScopeAnalysis
650  : RuntimeCallCounterId::kCompileScopeAnalysis);
651  DCHECK_NOT_NULL(info->literal());
652  DeclarationScope* scope = info->literal()->scope();
653 
654  base::Optional<AllowHandleDereference> allow_deref;
655  if (!info->maybe_outer_scope_info().is_null()) {
656  // Allow dereferences to the scope info if there is one.
657  allow_deref.emplace();
658  }
659 
660  if (scope->is_eval_scope() && is_sloppy(scope->language_mode())) {
661  AstNodeFactory factory(info->ast_value_factory(), info->zone());
662  scope->HoistSloppyBlockFunctions(&factory);
663  }
664 
665  // We are compiling one of four cases:
666  // 1) top-level code,
667  // 2) a function/eval/module on the top-level
668  // 3) a function/eval in a scope that was already resolved.
669  DCHECK(scope->scope_type() == SCRIPT_SCOPE ||
670  scope->outer_scope()->scope_type() == SCRIPT_SCOPE ||
671  scope->outer_scope()->already_resolved_);
672 
673  // The outer scope is never lazy.
674  scope->set_should_eager_compile();
675 
676  if (scope->must_use_preparsed_scope_data_) {
677  DCHECK_EQ(scope->scope_type_, ScopeType::FUNCTION_SCOPE);
678  allow_deref.emplace();
679  info->consumed_preparsed_scope_data()->RestoreScopeAllocationData(scope);
680  }
681 
682  if (!scope->AllocateVariables(info)) return false;
683 
684 #ifdef DEBUG
685  if (info->is_native() ? FLAG_print_builtin_scopes : FLAG_print_scopes) {
686  PrintF("Global scope:\n");
687  scope->Print();
688  }
689  scope->CheckScopePositions();
690  scope->CheckZones();
691 #endif
692 
693  return true;
694 }
695 
696 void DeclarationScope::DeclareThis(AstValueFactory* ast_value_factory) {
697  DCHECK(!already_resolved_);
698  DCHECK(is_declaration_scope());
699  DCHECK(has_this_declaration());
700 
701  bool derived_constructor = IsDerivedConstructor(function_kind_);
702  Variable* var =
703  Declare(zone(), ast_value_factory->this_string(),
704  derived_constructor ? VariableMode::kConst : VariableMode::kVar,
705  THIS_VARIABLE,
706  derived_constructor ? kNeedsInitialization : kCreatedInitialized);
707  receiver_ = var;
708 }
709 
710 void DeclarationScope::DeclareArguments(AstValueFactory* ast_value_factory) {
711  DCHECK(is_function_scope());
712  DCHECK(!is_arrow_scope());
713 
714  arguments_ = LookupLocal(ast_value_factory->arguments_string());
715  if (arguments_ == nullptr) {
716  // Declare 'arguments' variable which exists in all non arrow functions.
717  // Note that it might never be accessed, in which case it won't be
718  // allocated during variable allocation.
719  arguments_ = Declare(zone(), ast_value_factory->arguments_string(),
720  VariableMode::kVar);
721  } else if (IsLexical(arguments_)) {
722  // Check if there's lexically declared variable named arguments to avoid
723  // redeclaration. See ES#sec-functiondeclarationinstantiation, step 20.
724  arguments_ = nullptr;
725  }
726 }
727 
728 void DeclarationScope::DeclareDefaultFunctionVariables(
729  AstValueFactory* ast_value_factory) {
730  DCHECK(is_function_scope());
731  DCHECK(!is_arrow_scope());
732 
733  DeclareThis(ast_value_factory);
734  new_target_ = Declare(zone(), ast_value_factory->new_target_string(),
735  VariableMode::kConst);
736 
737  if (IsConciseMethod(function_kind_) || IsClassConstructor(function_kind_) ||
738  IsAccessorFunction(function_kind_)) {
739  EnsureRareData()->this_function =
740  Declare(zone(), ast_value_factory->this_function_string(),
741  VariableMode::kConst);
742  }
743 }
744 
745 Variable* DeclarationScope::DeclareFunctionVar(const AstRawString* name,
746  Scope* cache) {
747  DCHECK(is_function_scope());
748  DCHECK_NULL(function_);
749  if (cache == nullptr) cache = this;
750  DCHECK_NULL(cache->variables_.Lookup(name));
751  VariableKind kind = is_sloppy(language_mode()) ? SLOPPY_FUNCTION_NAME_VARIABLE
752  : NORMAL_VARIABLE;
753  function_ = new (zone())
754  Variable(this, name, VariableMode::kConst, kind, kCreatedInitialized);
755  if (calls_sloppy_eval()) {
756  cache->NonLocal(name, VariableMode::kDynamic);
757  } else {
758  cache->variables_.Add(zone(), function_);
759  }
760  return function_;
761 }
762 
763 Variable* DeclarationScope::DeclareGeneratorObjectVar(
764  const AstRawString* name) {
765  DCHECK(is_function_scope() || is_module_scope());
766  DCHECK_NULL(generator_object_var());
767 
768  Variable* result = EnsureRareData()->generator_object =
769  NewTemporary(name, kNotAssigned);
770  result->set_is_used();
771  return result;
772 }
773 
774 bool Scope::HasBeenRemoved() const {
775  if (sibling() == this) {
776  DCHECK_NULL(inner_scope_);
777  DCHECK(is_block_scope());
778  return true;
779  }
780  return false;
781 }
782 
783 Scope* Scope::GetUnremovedScope() {
784  Scope* scope = this;
785  while (scope != nullptr && scope->HasBeenRemoved()) {
786  scope = scope->outer_scope();
787  }
788  DCHECK_NOT_NULL(scope);
789  return scope;
790 }
791 
792 Scope* Scope::FinalizeBlockScope() {
793  DCHECK(is_block_scope());
794  DCHECK(!HasBeenRemoved());
795 
796  if (variables_.occupancy() > 0 ||
797  (is_declaration_scope() && AsDeclarationScope()->calls_sloppy_eval())) {
798  return this;
799  }
800 
801  // Remove this scope from outer scope.
802  outer_scope()->RemoveInnerScope(this);
803 
804  // Reparent inner scopes.
805  if (inner_scope_ != nullptr) {
806  Scope* scope = inner_scope_;
807  scope->outer_scope_ = outer_scope();
808  while (scope->sibling_ != nullptr) {
809  scope = scope->sibling_;
810  scope->outer_scope_ = outer_scope();
811  }
812  scope->sibling_ = outer_scope()->inner_scope_;
813  outer_scope()->inner_scope_ = inner_scope_;
814  inner_scope_ = nullptr;
815  }
816 
817  // Move unresolved variables
818  if (!unresolved_list_.is_empty()) {
819  outer_scope()->unresolved_list_.Prepend(std::move(unresolved_list_));
820  unresolved_list_.Clear();
821  }
822 
823  if (inner_scope_calls_eval_) outer_scope()->inner_scope_calls_eval_ = true;
824 
825  // No need to propagate scope_calls_eval_, since if it was relevant to
826  // this scope we would have had to bail out at the top.
827  DCHECK(!scope_calls_eval_ || !is_declaration_scope() ||
828  !is_sloppy(language_mode()));
829 
830  // This block does not need a context.
831  num_heap_slots_ = 0;
832 
833  // Mark scope as removed by making it its own sibling.
834  sibling_ = this;
835  DCHECK(HasBeenRemoved());
836 
837  return nullptr;
838 }
839 
840 void DeclarationScope::AddLocal(Variable* var) {
841  DCHECK(!already_resolved_);
842  // Temporaries are only placed in ClosureScopes.
843  DCHECK_EQ(GetClosureScope(), this);
844  locals_.Add(var);
845 }
846 
847 void Scope::Snapshot::Reparent(DeclarationScope* new_parent) {
848  DCHECK_EQ(new_parent, outer_scope_and_calls_eval_.GetPointer()->inner_scope_);
849  DCHECK_EQ(new_parent->outer_scope_, outer_scope_and_calls_eval_.GetPointer());
850  DCHECK_EQ(new_parent, new_parent->GetClosureScope());
851  DCHECK_NULL(new_parent->inner_scope_);
852  DCHECK(new_parent->unresolved_list_.is_empty());
853  DCHECK(new_parent->locals_.is_empty());
854  Scope* inner_scope = new_parent->sibling_;
855  if (inner_scope != top_inner_scope_) {
856  for (; inner_scope->sibling() != top_inner_scope_;
857  inner_scope = inner_scope->sibling()) {
858  inner_scope->outer_scope_ = new_parent;
859  if (inner_scope->inner_scope_calls_eval_) {
860  new_parent->inner_scope_calls_eval_ = true;
861  }
862  DCHECK_NE(inner_scope, new_parent);
863  }
864  inner_scope->outer_scope_ = new_parent;
865  if (inner_scope->inner_scope_calls_eval_) {
866  new_parent->inner_scope_calls_eval_ = true;
867  }
868  new_parent->inner_scope_ = new_parent->sibling_;
869  inner_scope->sibling_ = nullptr;
870  // Reset the sibling rather than the inner_scope_ since we
871  // want to keep new_parent there.
872  new_parent->sibling_ = top_inner_scope_;
873  }
874 
875  Scope* outer_scope_ = outer_scope_and_calls_eval_.GetPointer();
876  new_parent->unresolved_list_.MoveTail(&outer_scope_->unresolved_list_,
877  top_unresolved_);
878 
879  // Move temporaries allocated for complex parameter initializers.
880  DeclarationScope* outer_closure = outer_scope_->GetClosureScope();
881  new_parent->locals_.MoveTail(outer_closure->locals(), top_local_);
882  for (Variable* local : new_parent->locals_) {
883  DCHECK_EQ(VariableMode::kTemporary, local->mode());
884  DCHECK_EQ(local->scope(), local->scope()->GetClosureScope());
885  DCHECK_NE(local->scope(), new_parent);
886  local->set_scope(new_parent);
887  }
888  outer_closure->locals_.Rewind(top_local_);
889 
890  // Move eval calls since Snapshot's creation into new_parent.
891  if (outer_scope_and_calls_eval_.GetPayload()) {
892  new_parent->scope_calls_eval_ = true;
893  new_parent->inner_scope_calls_eval_ = true;
894  }
895 
896  Clear();
897 }
898 
899 void Scope::ReplaceOuterScope(Scope* outer) {
900  DCHECK_NOT_NULL(outer);
901  DCHECK_NOT_NULL(outer_scope_);
902  DCHECK(!already_resolved_);
903  outer_scope_->RemoveInnerScope(this);
904  outer->AddInnerScope(this);
905  outer_scope_ = outer;
906 }
907 
908 Variable* Scope::LookupInScopeInfo(const AstRawString* name, Scope* cache) {
909  DCHECK(!scope_info_.is_null());
910  DCHECK_NULL(cache->variables_.Lookup(name));
911 
912  Handle<String> name_handle = name->string();
913  // The Scope is backed up by ScopeInfo. This means it cannot operate in a
914  // heap-independent mode, and all strings must be internalized immediately. So
915  // it's ok to get the Handle<String> here.
916  bool found = false;
917 
918  VariableLocation location;
919  int index;
920  VariableMode mode;
921  InitializationFlag init_flag;
922  MaybeAssignedFlag maybe_assigned_flag;
923 
924  {
925  location = VariableLocation::CONTEXT;
926  index = ScopeInfo::ContextSlotIndex(scope_info_, name_handle, &mode,
927  &init_flag, &maybe_assigned_flag);
928  found = index >= 0;
929  }
930 
931  if (!found && scope_type() == MODULE_SCOPE) {
932  location = VariableLocation::MODULE;
933  index = scope_info_->ModuleIndex(name_handle, &mode, &init_flag,
934  &maybe_assigned_flag);
935  found = index != 0;
936  }
937 
938  if (!found) {
939  index = scope_info_->FunctionContextSlotIndex(*name_handle);
940  if (index < 0) return nullptr; // Nowhere found.
941  Variable* var = AsDeclarationScope()->DeclareFunctionVar(name, cache);
942  DCHECK_EQ(VariableMode::kConst, var->mode());
943  var->AllocateTo(VariableLocation::CONTEXT, index);
944  return cache->variables_.Lookup(name);
945  }
946 
947  VariableKind kind = NORMAL_VARIABLE;
948  if (location == VariableLocation::CONTEXT &&
949  index == scope_info_->ReceiverContextSlotIndex()) {
950  kind = THIS_VARIABLE;
951  }
952  // TODO(marja, rossberg): Correctly declare FUNCTION, CLASS, NEW_TARGET, and
953  // ARGUMENTS bindings as their corresponding VariableKind.
954 
955  Variable* var = cache->variables_.Declare(zone(), this, name, mode, kind,
956  init_flag, maybe_assigned_flag);
957  var->AllocateTo(location, index);
958  return var;
959 }
960 
961 Variable* DeclarationScope::DeclareParameter(const AstRawString* name,
962  VariableMode mode,
963  bool is_optional, bool is_rest,
964  AstValueFactory* ast_value_factory,
965  int position) {
966  DCHECK(!already_resolved_);
967  DCHECK(is_function_scope() || is_module_scope());
968  DCHECK(!has_rest_);
969  DCHECK(!is_optional || !is_rest);
970  DCHECK(!is_being_lazily_parsed_);
971  DCHECK(!was_lazily_parsed_);
972  Variable* var;
973  if (mode == VariableMode::kTemporary) {
974  var = NewTemporary(name);
975  } else {
976  DCHECK_EQ(mode, VariableMode::kVar);
977  var = Declare(zone(), name, mode);
978  }
979  has_rest_ = is_rest;
980  var->set_initializer_position(position);
981  params_.Add(var, zone());
982  if (name == ast_value_factory->arguments_string()) {
983  has_arguments_parameter_ = true;
984  }
985  return var;
986 }
987 
988 Variable* DeclarationScope::DeclareParameterName(
989  const AstRawString* name, bool is_rest, AstValueFactory* ast_value_factory,
990  bool declare_as_local, bool add_parameter) {
991  DCHECK(!already_resolved_);
992  DCHECK(is_function_scope() || is_module_scope());
993  DCHECK(!has_rest_ || is_rest);
994  DCHECK(is_being_lazily_parsed_);
995  has_rest_ = is_rest;
996  if (name == ast_value_factory->arguments_string()) {
997  has_arguments_parameter_ = true;
998  }
999  Variable* var;
1000  if (declare_as_local) {
1001  var = Declare(zone(), name, VariableMode::kVar);
1002  } else {
1003  var = new (zone()) Variable(this, name, VariableMode::kTemporary,
1004  NORMAL_VARIABLE, kCreatedInitialized);
1005  }
1006  if (add_parameter) {
1007  params_.Add(var, zone());
1008  }
1009  return var;
1010 }
1011 
1012 Variable* Scope::DeclareLocal(const AstRawString* name, VariableMode mode,
1013  InitializationFlag init_flag) {
1014  DCHECK(!already_resolved_);
1015  // This function handles VariableMode::kVar, VariableMode::kLet, and
1016  // VariableMode::kConst modes. VariableMode::kDynamic variables are
1017  // introduced during variable allocation, and VariableMode::kTemporary
1018  // variables are allocated via NewTemporary().
1019  DCHECK(IsDeclaredVariableMode(mode));
1020  DCHECK_IMPLIES(GetDeclarationScope()->is_being_lazily_parsed(),
1021  mode == VariableMode::kVar || mode == VariableMode::kLet ||
1022  mode == VariableMode::kConst);
1023  DCHECK(!GetDeclarationScope()->was_lazily_parsed());
1024  return Declare(zone(), name, mode, NORMAL_VARIABLE, init_flag);
1025 }
1026 
1027 Variable* Scope::DeclareVariable(
1028  Declaration* declaration, VariableMode mode, InitializationFlag init,
1029  bool* sloppy_mode_block_scope_function_redefinition, bool* ok) {
1030  DCHECK(IsDeclaredVariableMode(mode));
1031  DCHECK(!already_resolved_);
1032  DCHECK(!GetDeclarationScope()->is_being_lazily_parsed());
1033  DCHECK(!GetDeclarationScope()->was_lazily_parsed());
1034 
1035  if (mode == VariableMode::kVar && !is_declaration_scope()) {
1036  return GetDeclarationScope()->DeclareVariable(
1037  declaration, mode, init, sloppy_mode_block_scope_function_redefinition,
1038  ok);
1039  }
1040  DCHECK(!is_catch_scope());
1041  DCHECK(!is_with_scope());
1042  DCHECK(is_declaration_scope() ||
1043  (IsLexicalVariableMode(mode) && is_block_scope()));
1044 
1045  VariableProxy* proxy = declaration->proxy();
1046  DCHECK_NOT_NULL(proxy->raw_name());
1047  const AstRawString* name = proxy->raw_name();
1048 
1049  // Pessimistically assume that top-level variables will be assigned.
1050  //
1051  // Top-level variables in a script can be accessed by other scripts or even
1052  // become global properties. While this does not apply to top-level variables
1053  // in a module (assuming they are not exported), we must still mark these as
1054  // assigned because they might be accessed by a lazily parsed top-level
1055  // function, which, for efficiency, we preparse without variable tracking.
1056  if (is_script_scope() || is_module_scope()) {
1057  if (mode != VariableMode::kConst) proxy->set_is_assigned();
1058  }
1059 
1060  Variable* var = LookupLocal(name);
1061  // Declare the variable in the declaration scope.
1062  if (V8_LIKELY(var == nullptr)) {
1063  if (V8_UNLIKELY(is_eval_scope() && is_sloppy(language_mode()) &&
1064  mode == VariableMode::kVar)) {
1065  // In a var binding in a sloppy direct eval, pollute the enclosing scope
1066  // with this new binding by doing the following:
1067  // The proxy is bound to a lookup variable to force a dynamic declaration
1068  // using the DeclareEvalVar or DeclareEvalFunction runtime functions.
1069  var = new (zone())
1070  Variable(this, name, mode, NORMAL_VARIABLE, init, kMaybeAssigned);
1071  var->AllocateTo(VariableLocation::LOOKUP, -1);
1072  } else {
1073  // Declare the name.
1074  var = DeclareLocal(name, mode, init);
1075  }
1076  } else {
1077  var->set_maybe_assigned();
1078  if (V8_UNLIKELY(IsLexicalVariableMode(mode) ||
1079  IsLexicalVariableMode(var->mode()))) {
1080  // The name was declared in this scope before; check for conflicting
1081  // re-declarations. We have a conflict if either of the declarations is
1082  // not a var (in script scope, we also have to ignore legacy const for
1083  // compatibility). There is similar code in runtime.cc in the Declare
1084  // functions. The function CheckConflictingVarDeclarations checks for
1085  // var and let bindings from different scopes whereas this is a check
1086  // for conflicting declarations within the same scope. This check also
1087  // covers the special case
1088  //
1089  // function () { let x; { var x; } }
1090  //
1091  // because the var declaration is hoisted to the function scope where
1092  // 'x' is already bound.
1093  //
1094  // In harmony we treat re-declarations as early errors. See ES5 16 for a
1095  // definition of early errors.
1096  //
1097  // Allow duplicate function decls for web compat, see bug 4693. If the
1098  // duplication is allowed, then the var will show up in the
1099  // SloppyBlockFunctionMap.
1100  SloppyBlockFunctionMap* map =
1101  GetDeclarationScope()->sloppy_block_function_map();
1102  *ok =
1103  map != nullptr && declaration->IsFunctionDeclaration() &&
1104  declaration->AsFunctionDeclaration()
1105  ->declares_sloppy_block_function() &&
1106  map->Lookup(const_cast<AstRawString*>(name), name->Hash()) != nullptr;
1107  *sloppy_mode_block_scope_function_redefinition = *ok;
1108  }
1109  }
1110  DCHECK_NOT_NULL(var);
1111 
1112  // We add a declaration node for every declaration. The compiler
1113  // will only generate code if necessary. In particular, declarations
1114  // for inner local variables that do not represent functions won't
1115  // result in any generated code.
1116  //
1117  // This will lead to multiple declaration nodes for the
1118  // same variable if it is declared several times. This is not a
1119  // semantic issue, but it may be a performance issue since it may
1120  // lead to repeated DeclareEvalVar or DeclareEvalFunction calls.
1121  decls_.Add(declaration);
1122  proxy->BindTo(var);
1123  return var;
1124 }
1125 
1126 Variable* Scope::DeclareVariableName(const AstRawString* name,
1127  VariableMode mode) {
1128  DCHECK(IsDeclaredVariableMode(mode));
1129  DCHECK(!already_resolved_);
1130  DCHECK(GetDeclarationScope()->is_being_lazily_parsed());
1131 
1132  if (mode == VariableMode::kVar && !is_declaration_scope()) {
1133  return GetDeclarationScope()->DeclareVariableName(name, mode);
1134  }
1135  DCHECK(!is_with_scope());
1136  DCHECK(!is_eval_scope());
1137  DCHECK(is_declaration_scope() || IsLexicalVariableMode(mode));
1138  DCHECK(scope_info_.is_null());
1139 
1140  // Declare the variable in the declaration scope.
1141  Variable* var = LookupLocal(name);
1142  DCHECK_NE(var, kDummyPreParserLexicalVariable);
1143  DCHECK_NE(var, kDummyPreParserVariable);
1144  if (var == nullptr) {
1145  var = DeclareLocal(name, mode);
1146  } else if (IsLexicalVariableMode(mode) ||
1147  IsLexicalVariableMode(var->mode())) {
1148  // Duplicate functions are allowed in the sloppy mode, but if this is not
1149  // a function declaration, it's an error. This is an error PreParser
1150  // hasn't previously detected. TODO(marja): Investigate whether we can now
1151  // start returning this error.
1152  } else if (mode == VariableMode::kVar) {
1153  var->set_maybe_assigned();
1154  }
1155  var->set_is_used();
1156  return var;
1157 }
1158 
1159 void Scope::DeclareCatchVariableName(const AstRawString* name) {
1160  DCHECK(!already_resolved_);
1161  DCHECK(GetDeclarationScope()->is_being_lazily_parsed());
1162  DCHECK(is_catch_scope());
1163  DCHECK(scope_info_.is_null());
1164 
1165  Declare(zone(), name, VariableMode::kVar);
1166 }
1167 
1168 void Scope::AddUnresolved(VariableProxy* proxy) {
1169  DCHECK(!already_resolved_);
1170  DCHECK(!proxy->is_resolved());
1171  unresolved_list_.Add(proxy);
1172 }
1173 
1174 Variable* DeclarationScope::DeclareDynamicGlobal(const AstRawString* name,
1175  VariableKind kind,
1176  Scope* cache) {
1177  DCHECK(is_script_scope());
1178  return cache->variables_.Declare(zone(), this, name,
1179  VariableMode::kDynamicGlobal, kind);
1180  // TODO(neis): Mark variable as maybe-assigned?
1181 }
1182 
1183 bool Scope::RemoveUnresolved(VariableProxy* var) {
1184  return unresolved_list_.Remove(var);
1185 }
1186 
1187 void Scope::DeleteUnresolved(VariableProxy* var) {
1188  DCHECK(unresolved_list_.Contains(var));
1189  var->mark_removed_from_unresolved();
1190 }
1191 
1192 Variable* Scope::NewTemporary(const AstRawString* name) {
1193  return NewTemporary(name, kMaybeAssigned);
1194 }
1195 
1196 Variable* Scope::NewTemporary(const AstRawString* name,
1197  MaybeAssignedFlag maybe_assigned) {
1198  DeclarationScope* scope = GetClosureScope();
1199  Variable* var = new (zone()) Variable(scope, name, VariableMode::kTemporary,
1200  NORMAL_VARIABLE, kCreatedInitialized);
1201  scope->AddLocal(var);
1202  if (maybe_assigned == kMaybeAssigned) var->set_maybe_assigned();
1203  return var;
1204 }
1205 
1206 Declaration* Scope::CheckConflictingVarDeclarations() {
1207  for (Declaration* decl : decls_) {
1208  VariableMode mode = decl->proxy()->var()->mode();
1209 
1210  // Lexical vs lexical conflicts within the same scope have already been
1211  // captured in Parser::Declare. The only conflicts we still need to check
1212  // are lexical vs nested var, or any declarations within a declaration
1213  // block scope vs lexical declarations in its surrounding (function) scope.
1214  Scope* current = this;
1215  if (decl->IsVariableDeclaration() &&
1216  decl->AsVariableDeclaration()->AsNested() != nullptr) {
1217  DCHECK_EQ(mode, VariableMode::kVar);
1218  current = decl->AsVariableDeclaration()->AsNested()->scope();
1219  } else if (IsLexicalVariableMode(mode)) {
1220  if (!is_block_scope()) continue;
1221  DCHECK(is_declaration_scope());
1222  DCHECK_EQ(outer_scope()->scope_type(), FUNCTION_SCOPE);
1223  current = outer_scope();
1224  }
1225 
1226  // Iterate through all scopes until and including the declaration scope.
1227  while (true) {
1228  // There is a conflict if there exists a non-VAR binding.
1229  Variable* other_var =
1230  current->variables_.Lookup(decl->proxy()->raw_name());
1231  if (other_var != nullptr && IsLexicalVariableMode(other_var->mode())) {
1232  return decl;
1233  }
1234  if (current->is_declaration_scope()) break;
1235  current = current->outer_scope();
1236  }
1237  }
1238  return nullptr;
1239 }
1240 
1241 Declaration* Scope::CheckLexDeclarationsConflictingWith(
1242  const ZonePtrList<const AstRawString>& names) {
1243  DCHECK(is_block_scope());
1244  for (int i = 0; i < names.length(); ++i) {
1245  Variable* var = LookupLocal(names.at(i));
1246  if (var != nullptr) {
1247  // Conflict; find and return its declaration.
1248  DCHECK(IsLexicalVariableMode(var->mode()));
1249  const AstRawString* name = names.at(i);
1250  for (Declaration* decl : decls_) {
1251  if (decl->proxy()->raw_name() == name) return decl;
1252  }
1253  DCHECK(false);
1254  }
1255  }
1256  return nullptr;
1257 }
1258 
1259 bool DeclarationScope::AllocateVariables(ParseInfo* info) {
1260  // Module variables must be allocated before variable resolution
1261  // to ensure that UpdateNeedsHoleCheck() can detect import variables.
1262  if (is_module_scope()) AsModuleScope()->AllocateModuleVariables();
1263 
1264  if (!ResolveVariablesRecursively(info)) {
1265  DCHECK(info->pending_error_handler()->has_pending_error());
1266  return false;
1267  }
1268  AllocateVariablesRecursively();
1269 
1270  return true;
1271 }
1272 
1273 bool Scope::AllowsLazyParsingWithoutUnresolvedVariables(
1274  const Scope* outer) const {
1275  // If none of the outer scopes need to decide whether to context allocate
1276  // specific variables, we can preparse inner functions without unresolved
1277  // variables. Otherwise we need to find unresolved variables to force context
1278  // allocation of the matching declarations. We can stop at the outer scope for
1279  // the parse, since context allocation of those variables is already
1280  // guaranteed to be correct.
1281  for (const Scope* s = this; s != outer; s = s->outer_scope_) {
1282  // Eval forces context allocation on all outer scopes, so we don't need to
1283  // look at those scopes. Sloppy eval makes top-level non-lexical variables
1284  // dynamic, whereas strict-mode requires context allocation.
1285  if (s->is_eval_scope()) return is_sloppy(s->language_mode());
1286  // Catch scopes force context allocation of all variables.
1287  if (s->is_catch_scope()) continue;
1288  // With scopes do not introduce variables that need allocation.
1289  if (s->is_with_scope()) continue;
1290  DCHECK(s->is_module_scope() || s->is_block_scope() ||
1291  s->is_function_scope());
1292  return false;
1293  }
1294  return true;
1295 }
1296 
1297 bool DeclarationScope::AllowsLazyCompilation() const {
1298  return !force_eager_compilation_;
1299 }
1300 
1301 int Scope::ContextChainLength(Scope* scope) const {
1302  int n = 0;
1303  for (const Scope* s = this; s != scope; s = s->outer_scope_) {
1304  DCHECK_NOT_NULL(s); // scope must be in the scope chain
1305  if (s->NeedsContext()) n++;
1306  }
1307  return n;
1308 }
1309 
1310 int Scope::ContextChainLengthUntilOutermostSloppyEval() const {
1311  int result = 0;
1312  int length = 0;
1313 
1314  for (const Scope* s = this; s != nullptr; s = s->outer_scope()) {
1315  if (!s->NeedsContext()) continue;
1316  length++;
1317  if (s->is_declaration_scope() &&
1318  s->AsDeclarationScope()->calls_sloppy_eval()) {
1319  result = length;
1320  }
1321  }
1322 
1323  return result;
1324 }
1325 
1326 DeclarationScope* Scope::GetDeclarationScope() {
1327  Scope* scope = this;
1328  while (!scope->is_declaration_scope()) {
1329  scope = scope->outer_scope();
1330  }
1331  return scope->AsDeclarationScope();
1332 }
1333 
1334 const DeclarationScope* Scope::GetClosureScope() const {
1335  const Scope* scope = this;
1336  while (!scope->is_declaration_scope() || scope->is_block_scope()) {
1337  scope = scope->outer_scope();
1338  }
1339  return scope->AsDeclarationScope();
1340 }
1341 
1342 DeclarationScope* Scope::GetClosureScope() {
1343  Scope* scope = this;
1344  while (!scope->is_declaration_scope() || scope->is_block_scope()) {
1345  scope = scope->outer_scope();
1346  }
1347  return scope->AsDeclarationScope();
1348 }
1349 
1350 bool Scope::NeedsScopeInfo() const {
1351  DCHECK(!already_resolved_);
1352  DCHECK(GetClosureScope()->ShouldEagerCompile());
1353  // The debugger expects all functions to have scope infos.
1354  // TODO(jochen|yangguo): Remove this requirement.
1355  if (is_function_scope()) return true;
1356  return NeedsContext();
1357 }
1358 
1359 bool Scope::ShouldBanArguments() {
1360  return GetReceiverScope()->should_ban_arguments();
1361 }
1362 
1363 DeclarationScope* Scope::GetReceiverScope() {
1364  Scope* scope = this;
1365  while (!scope->is_script_scope() &&
1366  (!scope->is_function_scope() ||
1367  scope->AsDeclarationScope()->is_arrow_scope())) {
1368  scope = scope->outer_scope();
1369  }
1370  return scope->AsDeclarationScope();
1371 }
1372 
1373 Scope* Scope::GetOuterScopeWithContext() {
1374  Scope* scope = outer_scope_;
1375  while (scope && !scope->NeedsContext()) {
1376  scope = scope->outer_scope();
1377  }
1378  return scope;
1379 }
1380 
1381 void Scope::CollectNonLocals(DeclarationScope* max_outer_scope,
1382  Isolate* isolate, ParseInfo* info,
1383  Handle<StringSet>* non_locals) {
1384  // Module variables must be allocated before variable resolution
1385  // to ensure that UpdateNeedsHoleCheck() can detect import variables.
1386  if (is_module_scope()) AsModuleScope()->AllocateModuleVariables();
1387 
1388  // Lazy parsed declaration scopes are already partially analyzed. If there are
1389  // unresolved references remaining, they just need to be resolved in outer
1390  // scopes.
1391  Scope* lookup =
1392  is_declaration_scope() && AsDeclarationScope()->was_lazily_parsed()
1393  ? outer_scope()
1394  : this;
1395 
1396  for (VariableProxy* proxy : unresolved_list_) {
1397  DCHECK(!proxy->is_resolved());
1398  Variable* var =
1399  Lookup<kParsedScope>(proxy, lookup, max_outer_scope->outer_scope());
1400  if (var == nullptr) {
1401  *non_locals = StringSet::Add(isolate, *non_locals, proxy->name());
1402  } else {
1403  // In this case we need to leave scopes in a way that they can be
1404  // allocated. If we resolved variables from lazy parsed scopes, we need
1405  // to context allocate the var.
1406  ResolveTo(info, proxy, var);
1407  if (!var->is_dynamic() && lookup != this) var->ForceContextAllocation();
1408  }
1409  }
1410 
1411  // Clear unresolved_list_ as it's in an inconsistent state.
1412  unresolved_list_.Clear();
1413 
1414  for (Scope* scope = inner_scope_; scope != nullptr; scope = scope->sibling_) {
1415  scope->CollectNonLocals(max_outer_scope, isolate, info, non_locals);
1416  }
1417 }
1418 
1419 void Scope::AnalyzePartially(DeclarationScope* max_outer_scope,
1420  AstNodeFactory* ast_node_factory,
1421  UnresolvedList* new_unresolved_list) {
1422  DCHECK_IMPLIES(is_declaration_scope(),
1423  !AsDeclarationScope()->was_lazily_parsed());
1424 
1425  for (VariableProxy* proxy = unresolved_list_.first(); proxy != nullptr;
1426  proxy = proxy->next_unresolved()) {
1427  DCHECK(!proxy->is_resolved());
1428  Variable* var =
1429  Lookup<kParsedScope>(proxy, this, max_outer_scope->outer_scope());
1430  if (var == nullptr) {
1431  // Don't copy unresolved references to the script scope, unless it's a
1432  // reference to a private name or method. In that case keep it so we
1433  // can fail later.
1434  if (!max_outer_scope->outer_scope()->is_script_scope() ||
1435  proxy->is_private_name()) {
1436  VariableProxy* copy = ast_node_factory->CopyVariableProxy(proxy);
1437  new_unresolved_list->Add(copy);
1438  }
1439  } else if (var != Scope::kDummyPreParserVariable &&
1440  var != Scope::kDummyPreParserLexicalVariable) {
1441  var->set_is_used();
1442  if (proxy->is_assigned()) var->set_maybe_assigned();
1443  }
1444  }
1445 
1446  // Clear unresolved_list_ as it's in an inconsistent state.
1447  unresolved_list_.Clear();
1448 
1449  for (Scope* scope = inner_scope_; scope != nullptr; scope = scope->sibling_) {
1450  scope->AnalyzePartially(max_outer_scope, ast_node_factory,
1451  new_unresolved_list);
1452  }
1453 }
1454 
1455 Handle<StringSet> DeclarationScope::CollectNonLocals(
1456  Isolate* isolate, ParseInfo* info, Handle<StringSet> non_locals) {
1457  Scope::CollectNonLocals(this, isolate, info, &non_locals);
1458  return non_locals;
1459 }
1460 
1461 void DeclarationScope::ResetAfterPreparsing(AstValueFactory* ast_value_factory,
1462  bool aborted) {
1463  DCHECK(is_function_scope());
1464 
1465  // Reset all non-trivial members.
1466  if (!aborted || !IsArrowFunction(function_kind_)) {
1467  // Do not remove parameters when lazy parsing an Arrow Function has failed,
1468  // as the formal parameters are not re-parsed.
1469  params_.Clear();
1470  }
1471  decls_.Clear();
1472  locals_.Clear();
1473  inner_scope_ = nullptr;
1474  unresolved_list_.Clear();
1475  sloppy_block_function_map_ = nullptr;
1476  rare_data_ = nullptr;
1477  has_rest_ = false;
1478 
1479  DCHECK_NE(zone_, ast_value_factory->zone());
1480  zone_->ReleaseMemory();
1481 
1482  if (aborted) {
1483  // Prepare scope for use in the outer zone.
1484  zone_ = ast_value_factory->zone();
1485  variables_.Reset(ZoneAllocationPolicy(zone_));
1486  if (!IsArrowFunction(function_kind_)) {
1487  has_simple_parameters_ = true;
1488  DeclareDefaultFunctionVariables(ast_value_factory);
1489  }
1490  } else {
1491  // Make sure this scope isn't used for allocation anymore.
1492  zone_ = nullptr;
1493  variables_.Invalidate();
1494  }
1495 
1496 #ifdef DEBUG
1497  needs_migration_ = false;
1498  is_being_lazily_parsed_ = false;
1499 #endif
1500 
1501  was_lazily_parsed_ = !aborted;
1502 }
1503 
1504 void Scope::SavePreParsedScopeData() {
1505  if (PreParsedScopeDataBuilder::ScopeIsSkippableFunctionScope(this)) {
1506  AsDeclarationScope()->SavePreParsedScopeDataForDeclarationScope();
1507  }
1508 
1509  for (Scope* scope = inner_scope_; scope != nullptr; scope = scope->sibling_) {
1510  scope->SavePreParsedScopeData();
1511  }
1512 }
1513 
1514 void DeclarationScope::SavePreParsedScopeDataForDeclarationScope() {
1515  if (preparsed_scope_data_builder_ != nullptr) {
1516  preparsed_scope_data_builder_->SaveScopeAllocationData(this);
1517  }
1518 }
1519 
1520 void DeclarationScope::AnalyzePartially(AstNodeFactory* ast_node_factory) {
1521  DCHECK(!force_eager_compilation_);
1522  UnresolvedList new_unresolved_list;
1523  if (!IsArrowFunction(function_kind_) &&
1524  (!outer_scope_->is_script_scope() ||
1525  (preparsed_scope_data_builder_ != nullptr &&
1526  preparsed_scope_data_builder_->ContainsInnerFunctions()))) {
1527  // Try to resolve unresolved variables for this Scope and migrate those
1528  // which cannot be resolved inside. It doesn't make sense to try to resolve
1529  // them in the outer Scopes here, because they are incomplete.
1530  Scope::AnalyzePartially(this, ast_node_factory, &new_unresolved_list);
1531 
1532  // Migrate function_ to the right Zone.
1533  if (function_ != nullptr) {
1534  function_ = ast_node_factory->CopyVariable(function_);
1535  }
1536 
1537  SavePreParsedScopeData();
1538  }
1539 
1540 #ifdef DEBUG
1541  if (FLAG_print_scopes) {
1542  PrintF("Inner function scope:\n");
1543  Print();
1544  }
1545 #endif
1546 
1547  ResetAfterPreparsing(ast_node_factory->ast_value_factory(), false);
1548 
1549  unresolved_list_ = std::move(new_unresolved_list);
1550 }
1551 
1552 #ifdef DEBUG
1553 namespace {
1554 
1555 const char* Header(ScopeType scope_type, FunctionKind function_kind,
1556  bool is_declaration_scope) {
1557  switch (scope_type) {
1558  case EVAL_SCOPE: return "eval";
1559  // TODO(adamk): Should we print concise method scopes specially?
1560  case FUNCTION_SCOPE:
1561  if (IsGeneratorFunction(function_kind)) return "function*";
1562  if (IsAsyncFunction(function_kind)) return "async function";
1563  if (IsArrowFunction(function_kind)) return "arrow";
1564  return "function";
1565  case MODULE_SCOPE: return "module";
1566  case SCRIPT_SCOPE: return "global";
1567  case CATCH_SCOPE: return "catch";
1568  case BLOCK_SCOPE: return is_declaration_scope ? "varblock" : "block";
1569  case WITH_SCOPE: return "with";
1570  }
1571  UNREACHABLE();
1572 }
1573 
1574 void Indent(int n, const char* str) { PrintF("%*s%s", n, "", str); }
1575 
1576 void PrintName(const AstRawString* name) {
1577  PrintF("%.*s", name->length(), name->raw_data());
1578 }
1579 
1580 void PrintLocation(Variable* var) {
1581  switch (var->location()) {
1582  case VariableLocation::UNALLOCATED:
1583  break;
1584  case VariableLocation::PARAMETER:
1585  PrintF("parameter[%d]", var->index());
1586  break;
1587  case VariableLocation::LOCAL:
1588  PrintF("local[%d]", var->index());
1589  break;
1590  case VariableLocation::CONTEXT:
1591  PrintF("context[%d]", var->index());
1592  break;
1593  case VariableLocation::LOOKUP:
1594  PrintF("lookup");
1595  break;
1596  case VariableLocation::MODULE:
1597  PrintF("module");
1598  break;
1599  }
1600 }
1601 
1602 void PrintVar(int indent, Variable* var) {
1603  Indent(indent, VariableMode2String(var->mode()));
1604  PrintF(" ");
1605  if (var->raw_name()->IsEmpty())
1606  PrintF(".%p", reinterpret_cast<void*>(var));
1607  else
1608  PrintName(var->raw_name());
1609  PrintF("; // (%p) ", reinterpret_cast<void*>(var));
1610  PrintLocation(var);
1611  bool comma = !var->IsUnallocated();
1612  if (var->has_forced_context_allocation()) {
1613  if (comma) PrintF(", ");
1614  PrintF("forced context allocation");
1615  comma = true;
1616  }
1617  if (var->maybe_assigned() == kNotAssigned) {
1618  if (comma) PrintF(", ");
1619  PrintF("never assigned");
1620  comma = true;
1621  }
1622  if (var->initialization_flag() == kNeedsInitialization &&
1623  !var->binding_needs_init()) {
1624  if (comma) PrintF(", ");
1625  PrintF("hole initialization elided");
1626  }
1627  PrintF("\n");
1628 }
1629 
1630 void PrintMap(int indent, const char* label, VariableMap* map, bool locals,
1631  Variable* function_var) {
1632  bool printed_label = false;
1633  for (VariableMap::Entry* p = map->Start(); p != nullptr; p = map->Next(p)) {
1634  Variable* var = reinterpret_cast<Variable*>(p->value);
1635  if (var == function_var) continue;
1636  if (var == Scope::kDummyPreParserVariable ||
1637  var == Scope::kDummyPreParserLexicalVariable) {
1638  continue;
1639  }
1640  bool local = !IsDynamicVariableMode(var->mode());
1641  if ((locals ? local : !local) &&
1642  (var->is_used() || !var->IsUnallocated())) {
1643  if (!printed_label) {
1644  Indent(indent, label);
1645  printed_label = true;
1646  }
1647  PrintVar(indent, var);
1648  }
1649  }
1650 }
1651 
1652 } // anonymous namespace
1653 
1654 void DeclarationScope::PrintParameters() {
1655  PrintF(" (");
1656  for (int i = 0; i < params_.length(); i++) {
1657  if (i > 0) PrintF(", ");
1658  const AstRawString* name = params_[i]->raw_name();
1659  if (name->IsEmpty())
1660  PrintF(".%p", reinterpret_cast<void*>(params_[i]));
1661  else
1662  PrintName(name);
1663  }
1664  PrintF(")");
1665 }
1666 
1667 void Scope::Print(int n) {
1668  int n0 = (n > 0 ? n : 0);
1669  int n1 = n0 + 2; // indentation
1670 
1671  // Print header.
1672  FunctionKind function_kind = is_function_scope()
1673  ? AsDeclarationScope()->function_kind()
1674  : kNormalFunction;
1675  Indent(n0, Header(scope_type_, function_kind, is_declaration_scope()));
1676  if (scope_name_ != nullptr && !scope_name_->IsEmpty()) {
1677  PrintF(" ");
1678  PrintName(scope_name_);
1679  }
1680 
1681  // Print parameters, if any.
1682  Variable* function = nullptr;
1683  if (is_function_scope()) {
1684  AsDeclarationScope()->PrintParameters();
1685  function = AsDeclarationScope()->function_var();
1686  }
1687 
1688  PrintF(" { // (%p) (%d, %d)\n", reinterpret_cast<void*>(this),
1689  start_position(), end_position());
1690  if (is_hidden()) {
1691  Indent(n1, "// is hidden\n");
1692  }
1693 
1694  // Function name, if any (named function literals, only).
1695  if (function != nullptr) {
1696  Indent(n1, "// (local) function name: ");
1697  PrintName(function->raw_name());
1698  PrintF("\n");
1699  }
1700 
1701  // Scope info.
1702  if (is_strict(language_mode())) {
1703  Indent(n1, "// strict mode scope\n");
1704  }
1705  if (IsAsmModule()) Indent(n1, "// scope is an asm module\n");
1706  if (is_declaration_scope() && AsDeclarationScope()->calls_sloppy_eval()) {
1707  Indent(n1, "// scope calls sloppy 'eval'\n");
1708  }
1709  if (is_declaration_scope() && AsDeclarationScope()->NeedsHomeObject()) {
1710  Indent(n1, "// scope needs home object\n");
1711  }
1712  if (inner_scope_calls_eval_) Indent(n1, "// inner scope calls 'eval'\n");
1713  if (is_declaration_scope()) {
1714  DeclarationScope* scope = AsDeclarationScope();
1715  if (scope->was_lazily_parsed()) Indent(n1, "// lazily parsed\n");
1716  if (scope->ShouldEagerCompile()) Indent(n1, "// will be compiled\n");
1717  }
1718  if (num_stack_slots_ > 0) {
1719  Indent(n1, "// ");
1720  PrintF("%d stack slots\n", num_stack_slots_);
1721  }
1722  if (num_heap_slots_ > 0) {
1723  Indent(n1, "// ");
1724  PrintF("%d heap slots\n", num_heap_slots_);
1725  }
1726 
1727  // Print locals.
1728  if (function != nullptr) {
1729  Indent(n1, "// function var:\n");
1730  PrintVar(n1, function);
1731  }
1732 
1733  // Print temporaries.
1734  {
1735  bool printed_header = false;
1736  for (Variable* local : locals_) {
1737  if (local->mode() != VariableMode::kTemporary) continue;
1738  if (!printed_header) {
1739  printed_header = true;
1740  Indent(n1, "// temporary vars:\n");
1741  }
1742  PrintVar(n1, local);
1743  }
1744  }
1745 
1746  if (variables_.occupancy() > 0) {
1747  PrintMap(n1, "// local vars:\n", &variables_, true, function);
1748  PrintMap(n1, "// dynamic vars:\n", &variables_, false, function);
1749  }
1750 
1751  // Print inner scopes (disable by providing negative n).
1752  if (n >= 0) {
1753  for (Scope* scope = inner_scope_; scope != nullptr;
1754  scope = scope->sibling_) {
1755  PrintF("\n");
1756  scope->Print(n1);
1757  }
1758  }
1759 
1760  Indent(n0, "}\n");
1761 }
1762 
1763 void Scope::CheckScopePositions() {
1764  // Visible leaf scopes must have real positions.
1765  if (!is_hidden() && inner_scope_ == nullptr) {
1766  DCHECK_NE(kNoSourcePosition, start_position());
1767  DCHECK_NE(kNoSourcePosition, end_position());
1768  }
1769  for (Scope* scope = inner_scope_; scope != nullptr; scope = scope->sibling_) {
1770  scope->CheckScopePositions();
1771  }
1772 }
1773 
1774 void Scope::CheckZones() {
1775  DCHECK(!needs_migration_);
1776  for (Scope* scope = inner_scope_; scope != nullptr; scope = scope->sibling_) {
1777  if (scope->is_declaration_scope() &&
1778  scope->AsDeclarationScope()->was_lazily_parsed()) {
1779  DCHECK_NULL(scope->zone());
1780  DCHECK_NULL(scope->inner_scope_);
1781  continue;
1782  }
1783  scope->CheckZones();
1784  }
1785 }
1786 #endif // DEBUG
1787 
1788 Variable* Scope::NonLocal(const AstRawString* name, VariableMode mode) {
1789  // Declare a new non-local.
1790  DCHECK(IsDynamicVariableMode(mode));
1791  Variable* var = variables_.Declare(zone(), nullptr, name, mode);
1792  // Allocate it by giving it a dynamic lookup.
1793  var->AllocateTo(VariableLocation::LOOKUP, -1);
1794  return var;
1795 }
1796 
1797 // static
1798 template <Scope::ScopeLookupMode mode>
1799 Variable* Scope::Lookup(VariableProxy* proxy, Scope* scope,
1800  Scope* outer_scope_end, Scope* entry_point,
1801  bool force_context_allocation) {
1802  if (mode == kDeserializedScope) {
1803  Variable* var = entry_point->variables_.Lookup(proxy->raw_name());
1804  if (var != nullptr) return var;
1805  }
1806 
1807  while (true) {
1808  DCHECK_IMPLIES(mode == kParsedScope, !scope->is_debug_evaluate_scope_);
1809  // Short-cut: whenever we find a debug-evaluate scope, just look everything
1810  // up dynamically. Debug-evaluate doesn't properly create scope info for the
1811  // lookups it does. It may not have a valid 'this' declaration, and anything
1812  // accessed through debug-evaluate might invalidly resolve to
1813  // stack-allocated variables.
1814  // TODO(yangguo): Remove once debug-evaluate creates proper ScopeInfo for
1815  // the scopes in which it's evaluating.
1816  if (mode == kDeserializedScope &&
1817  V8_UNLIKELY(scope->is_debug_evaluate_scope_)) {
1818  return entry_point->NonLocal(proxy->raw_name(), VariableMode::kDynamic);
1819  }
1820 
1821  // Try to find the variable in this scope.
1822  Variable* var = mode == kParsedScope ? scope->LookupLocal(proxy->raw_name())
1823  : scope->LookupInScopeInfo(
1824  proxy->raw_name(), entry_point);
1825 
1826  // We found a variable and we are done. (Even if there is an 'eval' in this
1827  // scope which introduces the same variable again, the resulting variable
1828  // remains the same.)
1829  if (var != nullptr) {
1830  if (mode == kParsedScope && force_context_allocation &&
1831  !var->is_dynamic()) {
1832  var->ForceContextAllocation();
1833  }
1834  return var;
1835  }
1836 
1837  if (scope->outer_scope_ == outer_scope_end) break;
1838 
1839  DCHECK(!scope->is_script_scope());
1840  if (V8_UNLIKELY(scope->is_with_scope())) {
1841  return LookupWith(proxy, scope, outer_scope_end, entry_point,
1842  force_context_allocation);
1843  }
1844  if (V8_UNLIKELY(scope->is_declaration_scope() &&
1845  scope->AsDeclarationScope()->calls_sloppy_eval())) {
1846  return LookupSloppyEval(proxy, scope, outer_scope_end, entry_point,
1847  force_context_allocation);
1848  }
1849 
1850  force_context_allocation |= scope->is_function_scope();
1851  scope = scope->outer_scope_;
1852  // TODO(verwaest): Separate through AnalyzePartially.
1853  if (mode == kParsedScope && !scope->scope_info_.is_null()) {
1854  return Lookup<kDeserializedScope>(proxy, scope, outer_scope_end, scope);
1855  }
1856  }
1857 
1858  // We may just be trying to find all free variables. In that case, don't
1859  // declare them in the outer scope.
1860  // TODO(marja): Separate Lookup for preparsed scopes better.
1861  if (mode == kParsedScope && !scope->is_script_scope()) {
1862  return nullptr;
1863  }
1864  if (V8_UNLIKELY(proxy->is_private_name())) return nullptr;
1865 
1866  // No binding has been found. Declare a variable on the global object.
1867  return scope->AsDeclarationScope()->DeclareDynamicGlobal(
1868  proxy->raw_name(), NORMAL_VARIABLE,
1869  mode == kDeserializedScope ? entry_point : scope);
1870 }
1871 
1872 template Variable* Scope::Lookup<Scope::kParsedScope>(
1873  VariableProxy* proxy, Scope* scope, Scope* outer_scope_end,
1874  Scope* entry_point, bool force_context_allocation);
1875 template Variable* Scope::Lookup<Scope::kDeserializedScope>(
1876  VariableProxy* proxy, Scope* scope, Scope* outer_scope_end,
1877  Scope* entry_point, bool force_context_allocation);
1878 
1879 namespace {
1880 bool CanBeShadowed(Scope* scope, Variable* var) {
1881  if (var == nullptr) return false;
1882 
1883  // TODO(marja): Separate Lookup for preparsed scopes better.
1884  if (var == Scope::kDummyPreParserVariable ||
1885  var == Scope::kDummyPreParserLexicalVariable) {
1886  DCHECK(scope->GetDeclarationScope()->is_being_lazily_parsed());
1887  return false;
1888  }
1889 
1890  // "this" can't be shadowed by "eval"-introduced bindings or by "with" scopes.
1891  // TODO(wingo): There are other variables in this category; add them.
1892  return !var->is_this();
1893 }
1894 }; // namespace
1895 
1896 Variable* Scope::LookupWith(VariableProxy* proxy, Scope* scope,
1897  Scope* outer_scope_end, Scope* entry_point,
1898  bool force_context_allocation) {
1899  DCHECK(scope->is_with_scope());
1900 
1901  Variable* var =
1902  scope->outer_scope_->scope_info_.is_null()
1903  ? Lookup<kParsedScope>(proxy, scope->outer_scope_, outer_scope_end,
1904  nullptr, force_context_allocation)
1905  : Lookup<kDeserializedScope>(proxy, scope->outer_scope_,
1906  outer_scope_end, entry_point);
1907 
1908  if (!CanBeShadowed(scope, var)) return var;
1909 
1910  // The current scope is a with scope, so the variable binding can not be
1911  // statically resolved. However, note that it was necessary to do a lookup
1912  // in the outer scope anyway, because if a binding exists in an outer
1913  // scope, the associated variable has to be marked as potentially being
1914  // accessed from inside of an inner with scope (the property may not be in
1915  // the 'with' object).
1916  if (!var->is_dynamic() && var->IsUnallocated()) {
1917  DCHECK(!scope->already_resolved_);
1918  var->set_is_used();
1919  var->ForceContextAllocation();
1920  if (proxy->is_assigned()) var->set_maybe_assigned();
1921  }
1922  if (entry_point != nullptr) entry_point->variables_.Remove(var);
1923  Scope* target = entry_point == nullptr ? scope : entry_point;
1924  return target->NonLocal(proxy->raw_name(), VariableMode::kDynamic);
1925 }
1926 
1927 Variable* Scope::LookupSloppyEval(VariableProxy* proxy, Scope* scope,
1928  Scope* outer_scope_end, Scope* entry_point,
1929  bool force_context_allocation) {
1930  DCHECK(scope->is_declaration_scope() &&
1931  scope->AsDeclarationScope()->calls_sloppy_eval());
1932 
1933  // If we're compiling eval, it's possible that the outer scope is the first
1934  // ScopeInfo-backed scope.
1935  Scope* entry = entry_point == nullptr ? scope->outer_scope_ : entry_point;
1936  Variable* var =
1937  scope->outer_scope_->scope_info_.is_null()
1938  ? Lookup<kParsedScope>(proxy, scope->outer_scope_, outer_scope_end,
1939  nullptr, force_context_allocation)
1940  : Lookup<kDeserializedScope>(proxy, scope->outer_scope_,
1941  outer_scope_end, entry);
1942  if (!CanBeShadowed(scope, var)) return var;
1943 
1944  // A variable binding may have been found in an outer scope, but the current
1945  // scope makes a sloppy 'eval' call, so the found variable may not be the
1946  // correct one (the 'eval' may introduce a binding with the same name). In
1947  // that case, change the lookup result to reflect this situation. Only
1948  // scopes that can host var bindings (declaration scopes) need be considered
1949  // here (this excludes block and catch scopes), and variable lookups at
1950  // script scope are always dynamic.
1951  if (var->IsGlobalObjectProperty()) {
1952  Scope* target = entry_point == nullptr ? scope : entry_point;
1953  return target->NonLocal(proxy->raw_name(), VariableMode::kDynamicGlobal);
1954  }
1955 
1956  if (var->is_dynamic()) return var;
1957 
1958  Variable* invalidated = var;
1959  if (entry_point != nullptr) entry_point->variables_.Remove(invalidated);
1960 
1961  Scope* target = entry_point == nullptr ? scope : entry_point;
1962  var = target->NonLocal(proxy->raw_name(), VariableMode::kDynamicLocal);
1963  var->set_local_if_not_shadowed(invalidated);
1964 
1965  return var;
1966 }
1967 
1968 bool Scope::ResolveVariable(ParseInfo* info, VariableProxy* proxy) {
1969  DCHECK(info->script_scope()->is_script_scope());
1970  DCHECK(!proxy->is_resolved());
1971  Variable* var = Lookup<kParsedScope>(proxy, this, nullptr);
1972  if (var == nullptr) {
1973  DCHECK(proxy->is_private_name());
1974  info->pending_error_handler()->ReportMessageAt(
1975  proxy->position(), proxy->position() + 1,
1976  MessageTemplate::kInvalidPrivateFieldAccess, proxy->raw_name(),
1977  kSyntaxError);
1978  return false;
1979  }
1980  ResolveTo(info, proxy, var);
1981  return true;
1982 }
1983 
1984 namespace {
1985 
1986 void SetNeedsHoleCheck(Variable* var, VariableProxy* proxy) {
1987  proxy->set_needs_hole_check();
1988  var->ForceHoleInitialization();
1989 }
1990 
1991 void UpdateNeedsHoleCheck(Variable* var, VariableProxy* proxy, Scope* scope) {
1992  if (var->mode() == VariableMode::kDynamicLocal) {
1993  // Dynamically introduced variables never need a hole check (since they're
1994  // VariableMode::kVar bindings, either from var or function declarations),
1995  // but the variable they shadow might need a hole check, which we want to do
1996  // if we decide that no shadowing variable was dynamically introoduced.
1997  DCHECK_EQ(kCreatedInitialized, var->initialization_flag());
1998  return UpdateNeedsHoleCheck(var->local_if_not_shadowed(), proxy, scope);
1999  }
2000 
2001  if (var->initialization_flag() == kCreatedInitialized) return;
2002 
2003  // It's impossible to eliminate module import hole checks here, because it's
2004  // unknown at compilation time whether the binding referred to in the
2005  // exporting module itself requires hole checks.
2006  if (var->location() == VariableLocation::MODULE && !var->IsExport()) {
2007  return SetNeedsHoleCheck(var, proxy);
2008  }
2009 
2010  // Check if the binding really needs an initialization check. The check
2011  // can be skipped in the following situation: we have a VariableMode::kLet or
2012  // VariableMode::kConst binding, both the Variable and the VariableProxy have
2013  // the same declaration scope (i.e. they are both in global code, in the same
2014  // function or in the same eval code), the VariableProxy is in the source
2015  // physically located after the initializer of the variable, and that the
2016  // initializer cannot be skipped due to a nonlinear scope.
2017  //
2018  // The condition on the closure scopes is a conservative check for
2019  // nested functions that access a binding and are called before the
2020  // binding is initialized:
2021  // function() { f(); let x = 1; function f() { x = 2; } }
2022  //
2023  // The check cannot be skipped on non-linear scopes, namely switch
2024  // scopes, to ensure tests are done in cases like the following:
2025  // switch (1) { case 0: let x = 2; case 1: f(x); }
2026  // The scope of the variable needs to be checked, in case the use is
2027  // in a sub-block which may be linear.
2028  if (var->scope()->GetClosureScope() != scope->GetClosureScope()) {
2029  return SetNeedsHoleCheck(var, proxy);
2030  }
2031 
2032  if (var->is_this()) {
2033  DCHECK(IsDerivedConstructor(scope->GetClosureScope()->function_kind()));
2034  // TODO(littledan): implement 'this' hole check elimination.
2035  return SetNeedsHoleCheck(var, proxy);
2036  }
2037 
2038  // We should always have valid source positions.
2039  DCHECK_NE(var->initializer_position(), kNoSourcePosition);
2040  DCHECK_NE(proxy->position(), kNoSourcePosition);
2041 
2042  if (var->scope()->is_nonlinear() ||
2043  var->initializer_position() >= proxy->position()) {
2044  return SetNeedsHoleCheck(var, proxy);
2045  }
2046 }
2047 
2048 } // anonymous namespace
2049 
2050 void Scope::ResolveTo(ParseInfo* info, VariableProxy* proxy, Variable* var) {
2051 #ifdef DEBUG
2052  if (info->is_native()) {
2053  // To avoid polluting the global object in native scripts
2054  // - Variables must not be allocated to the global scope.
2055  DCHECK_NOT_NULL(outer_scope());
2056  // - Variables must be bound locally or unallocated.
2057  if (var->IsGlobalObjectProperty()) {
2058  // The following variable name may be minified. If so, disable
2059  // minification in js2c.py for better output.
2060  Handle<String> name = proxy->raw_name()->string();
2061  FATAL("Unbound variable: '%s' in native script.",
2062  name->ToCString().get());
2063  }
2064  VariableLocation location = var->location();
2065  DCHECK(location == VariableLocation::LOCAL ||
2066  location == VariableLocation::CONTEXT ||
2067  location == VariableLocation::PARAMETER ||
2068  location == VariableLocation::UNALLOCATED);
2069  }
2070 #endif
2071 
2072  DCHECK_NOT_NULL(var);
2073  UpdateNeedsHoleCheck(var, proxy, this);
2074  proxy->BindTo(var);
2075 }
2076 
2077 bool Scope::ResolveVariablesRecursively(ParseInfo* info) {
2078  DCHECK(info->script_scope()->is_script_scope());
2079  // Lazy parsed declaration scopes are already partially analyzed. If there are
2080  // unresolved references remaining, they just need to be resolved in outer
2081  // scopes.
2082  if (is_declaration_scope() && AsDeclarationScope()->was_lazily_parsed()) {
2083  DCHECK_EQ(variables_.occupancy(), 0);
2084  for (VariableProxy* proxy : unresolved_list_) {
2085  Variable* var = Lookup<kParsedScope>(proxy, outer_scope(), nullptr);
2086  if (var == nullptr) {
2087  info->pending_error_handler()->ReportMessageAt(
2088  proxy->position(), proxy->position() + 1,
2089  MessageTemplate::kInvalidPrivateFieldAccess, proxy->raw_name(),
2090  kSyntaxError);
2091  DCHECK(proxy->is_private_name());
2092  return false;
2093  }
2094  if (!var->is_dynamic()) {
2095  var->set_is_used();
2096  var->ForceContextAllocation();
2097  if (proxy->is_assigned()) var->set_maybe_assigned();
2098  }
2099  }
2100  } else {
2101  // Resolve unresolved variables for this scope.
2102  for (VariableProxy* proxy : unresolved_list_) {
2103  if (!ResolveVariable(info, proxy)) return false;
2104  }
2105 
2106  // Resolve unresolved variables for inner scopes.
2107  for (Scope* scope = inner_scope_; scope != nullptr;
2108  scope = scope->sibling_) {
2109  if (!scope->ResolveVariablesRecursively(info)) return false;
2110  }
2111  }
2112  return true;
2113 }
2114 
2115 bool Scope::MustAllocate(Variable* var) {
2116  if (var == kDummyPreParserLexicalVariable || var == kDummyPreParserVariable) {
2117  return true;
2118  }
2119  DCHECK(var->location() != VariableLocation::MODULE);
2120  // Give var a read/write use if there is a chance it might be accessed
2121  // via an eval() call. This is only possible if the variable has a
2122  // visible name.
2123  if ((var->is_this() || !var->raw_name()->IsEmpty()) &&
2124  (inner_scope_calls_eval_ || is_catch_scope() || is_script_scope())) {
2125  var->set_is_used();
2126  if (inner_scope_calls_eval_) var->set_maybe_assigned();
2127  }
2128  DCHECK(!var->has_forced_context_allocation() || var->is_used());
2129  // Global variables do not need to be allocated.
2130  return !var->IsGlobalObjectProperty() && var->is_used();
2131 }
2132 
2133 
2134 bool Scope::MustAllocateInContext(Variable* var) {
2135  // If var is accessed from an inner scope, or if there is a possibility
2136  // that it might be accessed from the current or an inner scope (through
2137  // an eval() call or a runtime with lookup), it must be allocated in the
2138  // context.
2139  //
2140  // Temporary variables are always stack-allocated. Catch-bound variables are
2141  // always context-allocated.
2142  if (var->mode() == VariableMode::kTemporary) return false;
2143  if (is_catch_scope()) return true;
2144  if ((is_script_scope() || is_eval_scope()) &&
2145  IsLexicalVariableMode(var->mode())) {
2146  return true;
2147  }
2148  return var->has_forced_context_allocation() || inner_scope_calls_eval_;
2149 }
2150 
2151 
2152 void Scope::AllocateStackSlot(Variable* var) {
2153  if (is_block_scope()) {
2154  outer_scope()->GetDeclarationScope()->AllocateStackSlot(var);
2155  } else {
2156  var->AllocateTo(VariableLocation::LOCAL, num_stack_slots_++);
2157  }
2158 }
2159 
2160 
2161 void Scope::AllocateHeapSlot(Variable* var) {
2162  var->AllocateTo(VariableLocation::CONTEXT, num_heap_slots_++);
2163 }
2164 
2165 void DeclarationScope::AllocateParameterLocals() {
2166  DCHECK(is_function_scope());
2167 
2168  bool has_mapped_arguments = false;
2169  if (arguments_ != nullptr) {
2170  DCHECK(!is_arrow_scope());
2171  if (MustAllocate(arguments_) && !has_arguments_parameter_) {
2172  // 'arguments' is used and does not refer to a function
2173  // parameter of the same name. If the arguments object
2174  // aliases formal parameters, we conservatively allocate
2175  // them specially in the loop below.
2176  has_mapped_arguments =
2177  GetArgumentsType() == CreateArgumentsType::kMappedArguments;
2178  } else {
2179  // 'arguments' is unused. Tell the code generator that it does not need to
2180  // allocate the arguments object by nulling out arguments_.
2181  arguments_ = nullptr;
2182  }
2183  }
2184 
2185  // The same parameter may occur multiple times in the parameters_ list.
2186  // If it does, and if it is not copied into the context object, it must
2187  // receive the highest parameter index for that parameter; thus iteration
2188  // order is relevant!
2189  for (int i = num_parameters() - 1; i >= 0; --i) {
2190  Variable* var = params_[i];
2191  DCHECK(!has_rest_ || var != rest_parameter());
2192  DCHECK_EQ(this, var->scope());
2193  if (has_mapped_arguments) {
2194  var->set_is_used();
2195  var->set_maybe_assigned();
2196  var->ForceContextAllocation();
2197  }
2198  AllocateParameter(var, i);
2199  }
2200 }
2201 
2202 void DeclarationScope::AllocateParameter(Variable* var, int index) {
2203  if (MustAllocate(var)) {
2204  if (has_forced_context_allocation_for_parameters() ||
2205  MustAllocateInContext(var)) {
2206  DCHECK(var->IsUnallocated() || var->IsContextSlot());
2207  if (var->IsUnallocated()) {
2208  AllocateHeapSlot(var);
2209  }
2210  } else {
2211  DCHECK(var->IsUnallocated() || var->IsParameter());
2212  if (var->IsUnallocated()) {
2213  var->AllocateTo(VariableLocation::PARAMETER, index);
2214  }
2215  }
2216  }
2217 }
2218 
2219 void DeclarationScope::AllocateReceiver() {
2220  if (!has_this_declaration()) return;
2221  DCHECK_NOT_NULL(receiver());
2222  DCHECK_EQ(receiver()->scope(), this);
2223  AllocateParameter(receiver(), -1);
2224 }
2225 
2226 void Scope::AllocateNonParameterLocal(Variable* var) {
2227  DCHECK(var->scope() == this);
2228  if (var->IsUnallocated() && MustAllocate(var)) {
2229  if (MustAllocateInContext(var)) {
2230  AllocateHeapSlot(var);
2231  DCHECK_IMPLIES(is_catch_scope(),
2232  var->index() == Context::THROWN_OBJECT_INDEX);
2233  } else {
2234  AllocateStackSlot(var);
2235  }
2236  }
2237 }
2238 
2239 void Scope::AllocateNonParameterLocalsAndDeclaredGlobals() {
2240  for (Variable* local : locals_) {
2241  AllocateNonParameterLocal(local);
2242  }
2243 
2244  if (is_declaration_scope()) {
2245  AsDeclarationScope()->AllocateLocals();
2246  }
2247 }
2248 
2249 void DeclarationScope::AllocateLocals() {
2250  // For now, function_ must be allocated at the very end. If it gets
2251  // allocated in the context, it must be the last slot in the context,
2252  // because of the current ScopeInfo implementation (see
2253  // ScopeInfo::ScopeInfo(FunctionScope* scope) constructor).
2254  if (function_ != nullptr && MustAllocate(function_)) {
2255  AllocateNonParameterLocal(function_);
2256  } else {
2257  function_ = nullptr;
2258  }
2259 
2260  DCHECK(!has_rest_ || !MustAllocate(rest_parameter()) ||
2261  !rest_parameter()->IsUnallocated());
2262 
2263  if (new_target_ != nullptr && !MustAllocate(new_target_)) {
2264  new_target_ = nullptr;
2265  }
2266 
2267  NullifyRareVariableIf(RareVariable::kThisFunction,
2268  [=](Variable* var) { return !MustAllocate(var); });
2269 }
2270 
2271 void ModuleScope::AllocateModuleVariables() {
2272  for (const auto& it : module()->regular_imports()) {
2273  Variable* var = LookupLocal(it.first);
2274  var->AllocateTo(VariableLocation::MODULE, it.second->cell_index);
2275  DCHECK(!var->IsExport());
2276  }
2277 
2278  for (const auto& it : module()->regular_exports()) {
2279  Variable* var = LookupLocal(it.first);
2280  var->AllocateTo(VariableLocation::MODULE, it.second->cell_index);
2281  DCHECK(var->IsExport());
2282  }
2283 }
2284 
2285 void Scope::AllocateVariablesRecursively() {
2286  DCHECK(!already_resolved_);
2287 
2288  // Don't allocate variables of preparsed scopes.
2289  if (is_declaration_scope() && AsDeclarationScope()->was_lazily_parsed()) {
2290  return;
2291  }
2292 
2293  // Allocate variables for inner scopes.
2294  for (Scope* scope = inner_scope_; scope != nullptr; scope = scope->sibling_) {
2295  scope->AllocateVariablesRecursively();
2296  }
2297 
2298  DCHECK(!already_resolved_);
2299  DCHECK_EQ(Context::MIN_CONTEXT_SLOTS, num_heap_slots_);
2300 
2301  // Allocate variables for this scope.
2302  // Parameters must be allocated first, if any.
2303  if (is_declaration_scope()) {
2304  if (is_function_scope()) {
2305  AsDeclarationScope()->AllocateParameterLocals();
2306  }
2307  AsDeclarationScope()->AllocateReceiver();
2308  }
2309  AllocateNonParameterLocalsAndDeclaredGlobals();
2310 
2311  // Force allocation of a context for this scope if necessary. For a 'with'
2312  // scope and for a function scope that makes an 'eval' call we need a context,
2313  // even if no local variables were statically allocated in the scope.
2314  // Likewise for modules and function scopes representing asm.js modules.
2315  bool must_have_context =
2316  is_with_scope() || is_module_scope() || IsAsmModule() ||
2317  (is_function_scope() && AsDeclarationScope()->calls_sloppy_eval()) ||
2318  (is_block_scope() && is_declaration_scope() &&
2319  AsDeclarationScope()->calls_sloppy_eval());
2320 
2321  // If we didn't allocate any locals in the local context, then we only
2322  // need the minimal number of slots if we must have a context.
2323  if (num_heap_slots_ == Context::MIN_CONTEXT_SLOTS && !must_have_context) {
2324  num_heap_slots_ = 0;
2325  }
2326 
2327  // Allocation done.
2328  DCHECK(num_heap_slots_ == 0 || num_heap_slots_ >= Context::MIN_CONTEXT_SLOTS);
2329 }
2330 
2331 void Scope::AllocateScopeInfosRecursively(Isolate* isolate,
2332  MaybeHandle<ScopeInfo> outer_scope) {
2333  DCHECK(scope_info_.is_null());
2334  MaybeHandle<ScopeInfo> next_outer_scope = outer_scope;
2335 
2336  if (NeedsScopeInfo()) {
2337  scope_info_ = ScopeInfo::Create(isolate, zone(), this, outer_scope);
2338  // The ScopeInfo chain should mirror the context chain, so we only link to
2339  // the next outer scope that needs a context.
2340  if (NeedsContext()) next_outer_scope = scope_info_;
2341  }
2342 
2343  // Allocate ScopeInfos for inner scopes.
2344  for (Scope* scope = inner_scope_; scope != nullptr; scope = scope->sibling_) {
2345  if (!scope->is_function_scope() ||
2346  scope->AsDeclarationScope()->ShouldEagerCompile()) {
2347  scope->AllocateScopeInfosRecursively(isolate, next_outer_scope);
2348  }
2349  }
2350 }
2351 
2352 // static
2353 void DeclarationScope::AllocateScopeInfos(ParseInfo* info, Isolate* isolate) {
2354  DeclarationScope* scope = info->literal()->scope();
2355  if (!scope->scope_info_.is_null()) return; // Allocated by outer function.
2356 
2357  MaybeHandle<ScopeInfo> outer_scope;
2358  if (scope->outer_scope_ != nullptr) {
2359  outer_scope = scope->outer_scope_->scope_info_;
2360  }
2361 
2362  scope->AllocateScopeInfosRecursively(isolate, outer_scope);
2363 
2364  // The debugger expects all shared function infos to contain a scope info.
2365  // Since the top-most scope will end up in a shared function info, make sure
2366  // it has one, even if it doesn't need a scope info.
2367  // TODO(jochen|yangguo): Remove this requirement.
2368  if (scope->scope_info_.is_null()) {
2369  scope->scope_info_ =
2370  ScopeInfo::Create(isolate, scope->zone(), scope, outer_scope);
2371  }
2372 
2373  // Ensuring that the outer script scope has a scope info avoids having
2374  // special case for native contexts vs other contexts.
2375  if (info->script_scope() && info->script_scope()->scope_info_.is_null()) {
2376  info->script_scope()->scope_info_ =
2377  handle(ScopeInfo::Empty(isolate), isolate);
2378  }
2379 }
2380 
2381 int Scope::StackLocalCount() const {
2382  Variable* function =
2383  is_function_scope() ? AsDeclarationScope()->function_var() : nullptr;
2384  return num_stack_slots() -
2385  (function != nullptr && function->IsStackLocal() ? 1 : 0);
2386 }
2387 
2388 
2389 int Scope::ContextLocalCount() const {
2390  if (num_heap_slots() == 0) return 0;
2391  Variable* function =
2392  is_function_scope() ? AsDeclarationScope()->function_var() : nullptr;
2393  bool is_function_var_in_context =
2394  function != nullptr && function->IsContextSlot();
2395  return num_heap_slots() - Context::MIN_CONTEXT_SLOTS -
2396  (is_function_var_in_context ? 1 : 0);
2397 }
2398 
2399 void* const Scope::kDummyPreParserVariable = reinterpret_cast<void*>(0x1);
2400 void* const Scope::kDummyPreParserLexicalVariable =
2401  reinterpret_cast<void*>(0x2);
2402 
2403 } // namespace internal
2404 } // namespace v8
Definition: libplatform.h:13