scopes.cc 84.6 KB
Newer Older
1
// Copyright 2012 the V8 project authors. All rights reserved.
2 3
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
4

5
#include "src/ast/scopes.h"
6

7 8
#include <set>

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/messages.h"
15
#include "src/objects-inl.h"
16
#include "src/objects/module.h"
17
#include "src/objects/scope-info.h"
18
#include "src/parsing/parse-info.h"
19
#include "src/parsing/preparsed-scope-data.h"
20

21 22
namespace v8 {
namespace internal {
23

24 25
namespace {
void* kDummyPreParserVariable = reinterpret_cast<void*>(0x1);
26 27 28 29 30 31 32 33
void* kDummyPreParserLexicalVariable = reinterpret_cast<void*>(0x2);

bool IsLexical(Variable* variable) {
  if (variable == kDummyPreParserLexicalVariable) return true;
  if (variable == kDummyPreParserVariable) return false;
  return IsLexicalVariableMode(variable->mode());
}

34 35
}  // namespace

36 37 38 39 40 41 42 43 44
// ----------------------------------------------------------------------------
// Implementation of LocalsMap
//
// Note: We are storing the handle locations as key values in the hash map.
//       When inserting a new variable via Declare(), we rely on the fact that
//       the handle location remains alive for the duration of that variable
//       use. Because a Variable holding a handle with the same location exists
//       this is ensured.

45
VariableMap::VariableMap(Zone* zone)
46
    : ZoneHashMap(8, ZoneAllocationPolicy(zone)) {}
47

verwaest's avatar
verwaest committed
48 49
Variable* VariableMap::Declare(Zone* zone, Scope* scope,
                               const AstRawString* name, VariableMode mode,
50
                               VariableKind kind,
51
                               InitializationFlag initialization_flag,
52 53
                               MaybeAssignedFlag maybe_assigned_flag,
                               bool* added) {
54 55 56
  // AstRawStrings are unambiguous, i.e., the same string is always represented
  // by the same AstRawString*.
  // FIXME(marja): fix the type of Lookup.
57
  Entry* p =
58
      ZoneHashMap::LookupOrInsert(const_cast<AstRawString*>(name), name->Hash(),
59
                                  ZoneAllocationPolicy(zone));
60 61
  if (added) *added = p->value == nullptr;
  if (p->value == nullptr) {
62
    // The variable has not been declared yet -> insert it.
63
    DCHECK_EQ(name, p->key);
verwaest's avatar
verwaest committed
64 65
    p->value = new (zone) Variable(scope, name, mode, kind, initialization_flag,
                                   maybe_assigned_flag);
66 67 68 69
  }
  return reinterpret_cast<Variable*>(p->value);
}

70 71
Variable* VariableMap::DeclareName(Zone* zone, const AstRawString* name,
                                   VariableMode mode) {
72
  Entry* p =
73
      ZoneHashMap::LookupOrInsert(const_cast<AstRawString*>(name), name->Hash(),
74 75 76 77
                                  ZoneAllocationPolicy(zone));
  if (p->value == nullptr) {
    // The variable has not been declared yet -> insert it.
    DCHECK_EQ(name, p->key);
78 79
    p->value =
        mode == VAR ? kDummyPreParserVariable : kDummyPreParserLexicalVariable;
80
  }
81
  return reinterpret_cast<Variable*>(p->value);
82 83
}

84 85
void VariableMap::Remove(Variable* var) {
  const AstRawString* name = var->raw_name();
86
  ZoneHashMap::Remove(const_cast<AstRawString*>(name), name->Hash());
87 88
}

89
void VariableMap::Add(Zone* zone, Variable* var) {
90
  const AstRawString* name = var->raw_name();
91
  Entry* p =
92
      ZoneHashMap::LookupOrInsert(const_cast<AstRawString*>(name), name->Hash(),
93
                                  ZoneAllocationPolicy(zone));
94 95 96 97
  DCHECK_NULL(p->value);
  DCHECK_EQ(name, p->key);
  p->value = var;
}
98

99
Variable* VariableMap::Lookup(const AstRawString* name) {
100
  Entry* p = ZoneHashMap::Lookup(const_cast<AstRawString*>(name), name->Hash());
101
  if (p != NULL) {
102 103
    DCHECK(reinterpret_cast<const AstRawString*>(p->key) == name);
    DCHECK(p->value != NULL);
104 105 106 107 108
    return reinterpret_cast<Variable*>(p->value);
  }
  return NULL;
}

109 110 111 112 113 114
void SloppyBlockFunctionMap::Delegate::set_statement(Statement* statement) {
  if (statement_ != nullptr) {
    statement_->set_statement(statement);
  }
}

115
SloppyBlockFunctionMap::SloppyBlockFunctionMap(Zone* zone)
116
    : ZoneHashMap(8, ZoneAllocationPolicy(zone)), count_(0) {}
117

118 119 120 121
void SloppyBlockFunctionMap::Declare(Zone* zone, const AstRawString* name,
                                     Scope* scope,
                                     SloppyBlockFunctionStatement* statement) {
  auto* delegate = new (zone) Delegate(scope, statement, count_++);
122 123
  // AstRawStrings are unambiguous, i.e., the same string is always represented
  // by the same AstRawString*.
124
  Entry* p =
125
      ZoneHashMap::LookupOrInsert(const_cast<AstRawString*>(name), name->Hash(),
126
                                  ZoneAllocationPolicy(zone));
127 128
  delegate->set_next(static_cast<SloppyBlockFunctionMap::Delegate*>(p->value));
  p->value = delegate;
129 130
}

131 132 133
// ----------------------------------------------------------------------------
// Implementation of Scope

134
Scope::Scope(Zone* zone)
135 136 137
    : zone_(zone),
      outer_scope_(nullptr),
      variables_(zone),
138
      scope_type_(SCRIPT_SCOPE) {
139 140 141
  SetDefaults();
}

142
Scope::Scope(Zone* zone, Scope* outer_scope, ScopeType scope_type)
verwaest's avatar
verwaest committed
143 144
    : zone_(zone),
      outer_scope_(outer_scope),
145
      variables_(zone),
146
      scope_type_(scope_type) {
147
  DCHECK_NE(SCRIPT_SCOPE, scope_type);
148
  SetDefaults();
149 150 151 152
  set_language_mode(outer_scope->language_mode());
  force_context_allocation_ =
      !is_function_scope() && outer_scope->has_forced_context_allocation();
  outer_scope_->AddInnerScope(this);
153 154
}

155 156 157 158
Scope::Snapshot::Snapshot(Scope* scope)
    : outer_scope_(scope),
      top_inner_scope_(scope->inner_scope_),
      top_unresolved_(scope->unresolved_),
159
      top_local_(scope->GetClosureScope()->locals_.end()),
160 161 162 163 164 165 166 167 168 169 170 171
      top_decl_(scope->GetClosureScope()->decls_.end()),
      outer_scope_calls_eval_(scope->scope_calls_eval_) {
  // Reset in order to record eval calls during this Snapshot's lifetime.
  outer_scope_->scope_calls_eval_ = false;
}

Scope::Snapshot::~Snapshot() {
  // Restore previous calls_eval bit if needed.
  if (outer_scope_calls_eval_) {
    outer_scope_->scope_calls_eval_ = true;
  }
}
172

173 174
DeclarationScope::DeclarationScope(Zone* zone,
                                   AstValueFactory* ast_value_factory)
175
    : Scope(zone), function_kind_(kNormalFunction), params_(4, zone) {
176
  DCHECK_EQ(scope_type_, SCRIPT_SCOPE);
177
  SetDefaults();
178 179 180

  // Make sure that if we don't find the global 'this', it won't be declared as
  // a regular dynamic global by predeclaring it with the right variable kind.
181
  DeclareDynamicGlobal(ast_value_factory->this_string(), THIS_VARIABLE);
182 183
}

184 185 186 187 188
DeclarationScope::DeclarationScope(Zone* zone, Scope* outer_scope,
                                   ScopeType scope_type,
                                   FunctionKind function_kind)
    : Scope(zone, outer_scope, scope_type),
      function_kind_(function_kind),
189
      params_(4, zone) {
190
  DCHECK_NE(scope_type, SCRIPT_SCOPE);
191
  SetDefaults();
192 193
}

194
ModuleScope::ModuleScope(DeclarationScope* script_scope,
195
                         AstValueFactory* ast_value_factory)
196 197
    : DeclarationScope(ast_value_factory->zone(), script_scope, MODULE_SCOPE,
                       kModule) {
198
  Zone* zone = ast_value_factory->zone();
199 200 201
  module_descriptor_ = new (zone) ModuleDescriptor(zone);
  set_language_mode(STRICT);
  DeclareThis(ast_value_factory);
202 203
}

204
ModuleScope::ModuleScope(Handle<ScopeInfo> scope_info,
205 206 207
                         AstValueFactory* avfactory)
    : DeclarationScope(avfactory->zone(), MODULE_SCOPE, scope_info) {
  Zone* zone = avfactory->zone();
208
  Isolate* isolate = scope_info->GetIsolate();
209
  Handle<ModuleInfo> module_info(scope_info->ModuleDescriptorInfo(), isolate);
210 211 212 213 214

  set_language_mode(STRICT);
  module_descriptor_ = new (zone) ModuleDescriptor(zone);

  // Deserialize special exports.
215
  Handle<FixedArray> special_exports(module_info->special_exports(), isolate);
216
  for (int i = 0, n = special_exports->length(); i < n; ++i) {
217 218
    Handle<ModuleInfoEntry> serialized_entry(
        ModuleInfoEntry::cast(special_exports->get(i)), isolate);
219 220 221 222 223 224 225
    module_descriptor_->AddSpecialExport(
        ModuleDescriptor::Entry::Deserialize(isolate, avfactory,
                                             serialized_entry),
        avfactory->zone());
  }

  // Deserialize regular exports.
226
  module_descriptor_->DeserializeRegularExports(isolate, avfactory,
227
                                                module_info);
228

229 230 231 232
  // Deserialize namespace imports.
  Handle<FixedArray> namespace_imports(module_info->namespace_imports(),
                                       isolate);
  for (int i = 0, n = namespace_imports->length(); i < n; ++i) {
233
    Handle<ModuleInfoEntry> serialized_entry(
234 235
        ModuleInfoEntry::cast(namespace_imports->get(i)), isolate);
    module_descriptor_->AddNamespaceImport(
236 237 238 239 240 241
        ModuleDescriptor::Entry::Deserialize(isolate, avfactory,
                                             serialized_entry),
        avfactory->zone());
  }

  // Deserialize regular imports.
242
  Handle<FixedArray> regular_imports(module_info->regular_imports(), isolate);
243 244 245 246 247 248
  for (int i = 0, n = regular_imports->length(); i < n; ++i) {
    Handle<ModuleInfoEntry> serialized_entry(
        ModuleInfoEntry::cast(regular_imports->get(i)), isolate);
    module_descriptor_->AddRegularImport(ModuleDescriptor::Entry::Deserialize(
        isolate, avfactory, serialized_entry));
  }
249 250
}

251
Scope::Scope(Zone* zone, ScopeType scope_type, Handle<ScopeInfo> scope_info)
verwaest's avatar
verwaest committed
252 253
    : zone_(zone),
      outer_scope_(nullptr),
254
      variables_(zone),
255
      scope_info_(scope_info),
256
      scope_type_(scope_type) {
257
  DCHECK(!scope_info.is_null());
258
  SetDefaults();
259 260 261
#ifdef DEBUG
  already_resolved_ = true;
#endif
262
  if (scope_info->CallsSloppyEval()) scope_calls_eval_ = true;
263 264
  set_language_mode(scope_info->language_mode());
  num_heap_slots_ = scope_info->ContextLength();
265
  DCHECK_LE(Context::MIN_CONTEXT_SLOTS, num_heap_slots_);
266 267 268
  // We don't really need to use the preparsed scope data; this is just to
  // shorten the recursion in SetMustUsePreParsedScopeData.
  must_use_preparsed_scope_data_ = true;
269 270
}

271
DeclarationScope::DeclarationScope(Zone* zone, ScopeType scope_type,
272
                                   Handle<ScopeInfo> scope_info)
273
    : Scope(zone, scope_type, scope_info),
274
      function_kind_(scope_info->function_kind()),
275
      params_(0, zone) {
276
  DCHECK_NE(scope_type, SCRIPT_SCOPE);
277 278 279
  SetDefaults();
}

280
Scope::Scope(Zone* zone, const AstRawString* catch_variable_name,
281
             MaybeAssignedFlag maybe_assigned, Handle<ScopeInfo> scope_info)
verwaest's avatar
verwaest committed
282 283
    : zone_(zone),
      outer_scope_(nullptr),
284
      variables_(zone),
285
      scope_info_(scope_info),
286
      scope_type_(CATCH_SCOPE) {
287
  SetDefaults();
288 289 290
#ifdef DEBUG
  already_resolved_ = true;
#endif
291 292 293
  // Cache the catch variable, even though it's also available via the
  // scope_info, as the parser expects that a catch scope always has the catch
  // variable as first and only variable.
294 295
  Variable* variable = Declare(zone, catch_variable_name, VAR, NORMAL_VARIABLE,
                               kCreatedInitialized, maybe_assigned);
296
  AllocateHeapSlot(variable);
297 298
}

299 300 301
void DeclarationScope::SetDefaults() {
  is_declaration_scope_ = true;
  has_simple_parameters_ = true;
302
  asm_module_ = false;
303
  force_eager_compilation_ = false;
304
  has_arguments_parameter_ = false;
305
  scope_uses_super_property_ = false;
306
  has_rest_ = false;
307
  sloppy_block_function_map_ = nullptr;
308 309 310 311
  receiver_ = nullptr;
  new_target_ = nullptr;
  function_ = nullptr;
  arguments_ = nullptr;
312
  rare_data_ = nullptr;
313
  should_eager_compile_ = false;
314
  was_lazily_parsed_ = false;
315
  is_skipped_function_ = false;
316
  produced_preparsed_scope_data_ = nullptr;
317 318 319 320 321 322 323
#ifdef DEBUG
  DeclarationScope* outer_declaration_scope =
      outer_scope_ ? outer_scope_->GetDeclarationScope() : nullptr;
  is_being_lazily_parsed_ =
      outer_declaration_scope ? outer_declaration_scope->is_being_lazily_parsed_
                              : false;
#endif
324 325 326 327 328
}

void Scope::SetDefaults() {
#ifdef DEBUG
  scope_name_ = nullptr;
329
  already_resolved_ = false;
330
  needs_migration_ = false;
331 332 333 334 335 336 337 338 339
#endif
  inner_scope_ = nullptr;
  sibling_ = nullptr;
  unresolved_ = nullptr;

  start_position_ = kNoSourcePosition;
  end_position_ = kNoSourcePosition;

  num_stack_slots_ = 0;
340
  num_heap_slots_ = Context::MIN_CONTEXT_SLOTS;
341

342
  set_language_mode(SLOPPY);
343

344
  scope_calls_eval_ = false;
345 346
  scope_nonlinear_ = false;
  is_hidden_ = false;
347
  is_debug_evaluate_scope_ = false;
348

349
  inner_scope_calls_eval_ = false;
350
  force_context_allocation_ = false;
351
  force_context_allocation_for_parameters_ = false;
352 353

  is_declaration_scope_ = false;
354 355

  must_use_preparsed_scope_data_ = false;
356 357 358 359 360
}

bool Scope::HasSimpleParameters() {
  DeclarationScope* scope = GetClosureScope();
  return !scope->is_function_scope() || scope->has_simple_parameters();
361 362
}

363
bool DeclarationScope::ShouldEagerCompile() const {
364
  return force_eager_compilation_ || should_eager_compile_;
365 366
}

367
void DeclarationScope::set_should_eager_compile() {
368
  should_eager_compile_ = !was_lazily_parsed_;
369 370
}

371 372 373 374
void DeclarationScope::set_asm_module() {
  asm_module_ = true;
}

375 376 377 378
bool Scope::IsAsmModule() const {
  return is_function_scope() && AsDeclarationScope()->asm_module();
}

379 380 381 382 383 384 385 386 387 388 389 390 391 392 393
bool Scope::ContainsAsmModule() const {
  if (IsAsmModule()) return true;

  // Check inner scopes recursively
  for (Scope* scope = inner_scope_; scope != nullptr; scope = scope->sibling_) {
    // Don't check inner functions which won't be eagerly compiled.
    if (!scope->is_function_scope() ||
        scope->AsDeclarationScope()->ShouldEagerCompile()) {
      if (scope->ContainsAsmModule()) return true;
    }
  }

  return false;
}

394
Scope* Scope::DeserializeScopeChain(Zone* zone, ScopeInfo* scope_info,
395
                                    DeclarationScope* script_scope,
396 397
                                    AstValueFactory* ast_value_factory,
                                    DeserializationMode deserialization_mode) {
398
  // Reconstruct the outer scope chain from a closure's context chain.
399 400
  Scope* current_scope = nullptr;
  Scope* innermost_scope = nullptr;
401
  Scope* outer_scope = nullptr;
402 403
  while (scope_info) {
    if (scope_info->scope_type() == WITH_SCOPE) {
404
      // For scope analysis, debug-evaluate is equivalent to a with scope.
405
      outer_scope = new (zone) Scope(zone, WITH_SCOPE, handle(scope_info));
406

407 408
      // TODO(yangguo): Remove once debug-evaluate properly keeps track of the
      // function scope in which we are evaluating.
409
      if (scope_info->IsDebugEvaluateScope()) {
410
        outer_scope->set_is_debug_evaluate_scope();
411
      }
412 413 414 415
    } else if (scope_info->scope_type() == SCRIPT_SCOPE) {
      // If we reach a script scope, it's the outermost scope. Install the
      // scope info of this script context onto the existing script scope to
      // avoid nesting script scopes.
416
      if (deserialization_mode == DeserializationMode::kIncludingVariables) {
417
        script_scope->SetScriptScopeInfo(handle(scope_info));
418
      }
419
      DCHECK(!scope_info->HasOuterScopeInfo());
420
      break;
421
    } else if (scope_info->scope_type() == FUNCTION_SCOPE) {
422
      outer_scope =
423
          new (zone) DeclarationScope(zone, FUNCTION_SCOPE, handle(scope_info));
424 425
      if (scope_info->IsAsmModule())
        outer_scope->AsDeclarationScope()->set_asm_module();
426 427 428
    } else if (scope_info->scope_type() == EVAL_SCOPE) {
      outer_scope =
          new (zone) DeclarationScope(zone, EVAL_SCOPE, handle(scope_info));
429
    } else if (scope_info->scope_type() == BLOCK_SCOPE) {
430
      if (scope_info->is_declaration_scope()) {
431
        outer_scope =
432
            new (zone) DeclarationScope(zone, BLOCK_SCOPE, handle(scope_info));
433
      } else {
434
        outer_scope = new (zone) Scope(zone, BLOCK_SCOPE, handle(scope_info));
435
      }
436
    } else if (scope_info->scope_type() == MODULE_SCOPE) {
437 438
      outer_scope =
          new (zone) ModuleScope(handle(scope_info), ast_value_factory);
439
    } else {
440 441
      DCHECK_EQ(scope_info->scope_type(), CATCH_SCOPE);
      DCHECK_EQ(scope_info->LocalCount(), 1);
442 443 444 445 446 447
      DCHECK_EQ(scope_info->ContextLocalCount(), 1);
      DCHECK_EQ(scope_info->ContextLocalMode(0), VAR);
      DCHECK_EQ(scope_info->ContextLocalInitFlag(0), kCreatedInitialized);
      String* name = scope_info->ContextLocalName(0);
      MaybeAssignedFlag maybe_assigned =
          scope_info->ContextLocalMaybeAssignedFlag(0);
448 449 450
      outer_scope =
          new (zone) Scope(zone, ast_value_factory->GetString(handle(name)),
                           maybe_assigned, handle(scope_info));
451
    }
452 453 454
    if (deserialization_mode == DeserializationMode::kScopesOnly) {
      outer_scope->scope_info_ = Handle<ScopeInfo>::null();
    }
455 456
    if (current_scope != nullptr) {
      outer_scope->AddInnerScope(current_scope);
457
    }
458
    current_scope = outer_scope;
459
    if (innermost_scope == nullptr) innermost_scope = current_scope;
460 461
    scope_info = scope_info->HasOuterScopeInfo() ? scope_info->OuterScopeInfo()
                                                 : nullptr;
462
  }
463

464
  if (innermost_scope == nullptr) return script_scope;
465
  script_scope->AddInnerScope(current_scope);
466
  return innermost_scope;
467 468
}

469 470 471 472 473 474 475 476 477 478
DeclarationScope* Scope::AsDeclarationScope() {
  DCHECK(is_declaration_scope());
  return static_cast<DeclarationScope*>(this);
}

const DeclarationScope* Scope::AsDeclarationScope() const {
  DCHECK(is_declaration_scope());
  return static_cast<const DeclarationScope*>(this);
}

479 480 481 482 483 484 485 486 487 488
ModuleScope* Scope::AsModuleScope() {
  DCHECK(is_module_scope());
  return static_cast<ModuleScope*>(this);
}

const ModuleScope* Scope::AsModuleScope() const {
  DCHECK(is_module_scope());
  return static_cast<const ModuleScope*>(this);
}

489 490 491 492
int Scope::num_parameters() const {
  return is_declaration_scope() ? AsDeclarationScope()->num_parameters() : 0;
}

493 494 495
void DeclarationScope::DeclareSloppyBlockFunction(
    const AstRawString* name, Scope* scope,
    SloppyBlockFunctionStatement* statement) {
496 497 498 499 500 501
  if (sloppy_block_function_map_ == nullptr) {
    sloppy_block_function_map_ =
        new (zone()->New(sizeof(SloppyBlockFunctionMap)))
            SloppyBlockFunctionMap(zone());
  }
  sloppy_block_function_map_->Declare(zone(), name, scope, statement);
502 503
}

504
void DeclarationScope::HoistSloppyBlockFunctions(AstNodeFactory* factory) {
505 506 507
  DCHECK(is_sloppy(language_mode()));
  DCHECK(is_function_scope() || is_eval_scope() || is_script_scope() ||
         (is_block_scope() && outer_scope()->is_function_scope()));
508 509 510
  DCHECK(HasSimpleParameters() || is_block_scope() || is_being_lazily_parsed_);
  DCHECK_EQ(factory == nullptr, is_being_lazily_parsed_);

511 512 513 514 515 516 517 518 519
  SloppyBlockFunctionMap* map = sloppy_block_function_map();
  if (map == nullptr) return;

  const bool has_simple_parameters = HasSimpleParameters();

  // The declarations need to be added in the order they were seen,
  // so accumulate declared names sorted by index.
  ZoneMap<int, const AstRawString*> names_to_declare(zone());

520 521 522
  // For each variable which is used as a function declaration in a sloppy
  // block,
  for (ZoneHashMap::Entry* p = map->Start(); p != nullptr; p = map->Next(p)) {
523
    const AstRawString* name = static_cast<AstRawString*>(p->key);
524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545

    // If the variable wouldn't conflict with a lexical declaration
    // or parameter,

    // Check if there's a conflict with a parameter.
    // This depends on the fact that functions always have a scope solely to
    // hold complex parameters, and the names local to that scope are
    // precisely the names of the parameters. IsDeclaredParameter(name) does
    // not hold for names declared by complex parameters, nor are those
    // bindings necessarily declared lexically, so we have to check for them
    // explicitly. On the other hand, if there are not complex parameters,
    // it is sufficient to just check IsDeclaredParameter.
    if (!has_simple_parameters) {
      if (outer_scope_->LookupLocal(name) != nullptr) {
        continue;
      }
    } else {
      if (IsDeclaredParameter(name)) {
        continue;
      }
    }

546
    bool declaration_queued = false;
547 548

    // Write in assignments to var for each block-scoped function declaration
549
    auto delegates = static_cast<SloppyBlockFunctionMap::Delegate*>(p->value);
550 551 552 553 554 555 556

    DeclarationScope* decl_scope = this;
    while (decl_scope->is_eval_scope()) {
      decl_scope = decl_scope->outer_scope()->GetDeclarationScope();
    }
    Scope* outer_scope = decl_scope->outer_scope();

557
    for (SloppyBlockFunctionMap::Delegate* delegate = delegates;
558 559 560 561 562 563 564 565 566 567 568 569 570
         delegate != nullptr; delegate = delegate->next()) {
      // Check if there's a conflict with a lexical declaration
      Scope* query_scope = delegate->scope()->outer_scope();
      Variable* var = nullptr;
      bool should_hoist = true;

      // Note that we perform this loop for each delegate named 'name',
      // which may duplicate work if those delegates share scopes.
      // It is not sufficient to just do a Lookup on query_scope: for
      // example, that does not prevent hoisting of the function in
      // `{ let e; try {} catch (e) { function e(){} } }`
      do {
        var = query_scope->LookupLocal(name);
571
        if (var != nullptr && IsLexical(var)) {
572 573 574 575 576 577 578 579
          should_hoist = false;
          break;
        }
        query_scope = query_scope->outer_scope();
      } while (query_scope != outer_scope);

      if (!should_hoist) continue;

580 581 582 583 584
      if (!declaration_queued) {
        declaration_queued = true;
        names_to_declare.insert({delegate->index(), name});
      }

585 586
      if (factory) {
        DCHECK(!is_being_lazily_parsed_);
587
        Assignment* assignment = factory->NewAssignment(
588 589
            Token::ASSIGN, NewUnresolved(factory, name),
            delegate->scope()->NewUnresolved(factory, name), kNoSourcePosition);
590
        assignment->set_lookup_hoisting_mode(LookupHoistingMode::kLegacySloppy);
591 592 593
        Statement* statement =
            factory->NewExpressionStatement(assignment, kNoSourcePosition);
        delegate->set_statement(statement);
594 595 596 597 598 599 600 601 602 603 604 605
      }
    }
  }

  if (names_to_declare.empty()) return;

  for (const auto& index_and_name : names_to_declare) {
    const AstRawString* name = index_and_name.second;
    if (factory) {
      DCHECK(!is_being_lazily_parsed_);
      VariableProxy* proxy = factory->NewVariableProxy(name, NORMAL_VARIABLE);
      auto declaration =
606
          factory->NewVariableDeclaration(proxy, kNoSourcePosition);
607 608 609 610 611 612 613 614 615 616 617 618 619
      // Based on the preceding checks, it doesn't matter what we pass as
      // allow_harmony_restrictive_generators and
      // sloppy_mode_block_scope_function_redefinition.
      bool ok = true;
      DeclareVariable(declaration, VAR,
                      Variable::DefaultInitializationFlag(VAR), false, nullptr,
                      &ok);
      DCHECK(ok);
    } else {
      DCHECK(is_being_lazily_parsed_);
      Variable* var = DeclareVariableName(name, VAR);
      if (var != kDummyPreParserVariable &&
          var != kDummyPreParserLexicalVariable) {
620
        DCHECK(FLAG_preparser_scope_analysis);
621
        var->set_maybe_assigned();
622
      }
623 624 625 626
    }
  }
}

627 628
void DeclarationScope::AttachOuterScopeInfo(ParseInfo* info, Isolate* isolate) {
  DCHECK(scope_info_.is_null());
629 630
  Handle<ScopeInfo> outer_scope_info;
  if (info->maybe_outer_scope_info().ToHandle(&outer_scope_info)) {
631 632 633 634
    // If we have a scope info we will potentially need to lookup variable names
    // on the scope info as internalized strings, so make sure ast_value_factory
    // is internalized.
    info->ast_value_factory()->Internalize(isolate);
635
    if (outer_scope()) {
636 637 638
      DeclarationScope* script_scope = new (info->zone())
          DeclarationScope(info->zone(), info->ast_value_factory());
      info->set_script_scope(script_scope);
639
      ReplaceOuterScope(Scope::DeserializeScopeChain(
640
          info->zone(), *outer_scope_info, script_scope,
641 642 643
          info->ast_value_factory(),
          Scope::DeserializationMode::kIncludingVariables));
    } else {
644
      DCHECK_EQ(outer_scope_info->scope_type(), SCRIPT_SCOPE);
645
      SetScriptScopeInfo(outer_scope_info);
646 647
    }
  }
648 649 650 651 652 653 654
}

void DeclarationScope::Analyze(ParseInfo* info) {
  RuntimeCallTimerScope runtimeTimer(info->runtime_call_stats(),
                                     &RuntimeCallStats::CompileScopeAnalysis);
  DCHECK(info->literal() != NULL);
  DeclarationScope* scope = info->literal()->scope();
655

656 657 658 659 660 661
  base::Optional<AllowHandleDereference> allow_deref;
  if (!info->maybe_outer_scope_info().is_null()) {
    // Allow dereferences to the scope info if there is one.
    allow_deref.emplace();
  }

662
  if (scope->is_eval_scope() && is_sloppy(scope->language_mode())) {
663
    AstNodeFactory factory(info->ast_value_factory(), info->zone());
664 665 666
    scope->HoistSloppyBlockFunctions(&factory);
  }

667
  // We are compiling one of four cases:
668 669 670
  // 1) top-level code,
  // 2) a function/eval/module on the top-level
  // 3) a function/eval in a scope that was already resolved.
671
  // 4) an asm.js function
672 673
  DCHECK(scope->scope_type() == SCRIPT_SCOPE ||
         scope->outer_scope()->scope_type() == SCRIPT_SCOPE ||
674 675
         scope->outer_scope()->already_resolved_ ||
         (info->asm_function_scope() && scope->is_function_scope()));
676

677
  // The outer scope is never lazy.
678
  scope->set_should_eager_compile();
679

680
  if (scope->must_use_preparsed_scope_data_) {
681
    DCHECK(FLAG_preparser_scope_analysis);
682
    DCHECK_EQ(scope->scope_type_, ScopeType::FUNCTION_SCOPE);
683
    allow_deref.emplace();
684
    info->consumed_preparsed_scope_data()->RestoreScopeAllocationData(scope);
685 686
  }

687
  scope->AllocateVariables(info);
688

689
#ifdef DEBUG
690
  if (info->is_native() ? FLAG_print_builtin_scopes : FLAG_print_scopes) {
691
    PrintF("Global scope:\n");
692
    scope->Print();
693
  }
694
  scope->CheckScopePositions();
695
  scope->CheckZones();
696 697 698
#endif
}

699
void DeclarationScope::DeclareThis(AstValueFactory* ast_value_factory) {
700
  DCHECK(!already_resolved_);
701 702 703
  DCHECK(is_declaration_scope());
  DCHECK(has_this_declaration());

704 705 706 707 708
  bool derived_constructor = IsDerivedConstructor(function_kind_);
  Variable* var =
      Declare(zone(), ast_value_factory->this_string(),
              derived_constructor ? CONST : VAR, THIS_VARIABLE,
              derived_constructor ? kNeedsInitialization : kCreatedInitialized);
709 710
  receiver_ = var;
}
711

712
void DeclarationScope::DeclareArguments(AstValueFactory* ast_value_factory) {
713 714
  DCHECK(is_function_scope());
  DCHECK(!is_arrow_scope());
715

716 717 718 719 720
  arguments_ = LookupLocal(ast_value_factory->arguments_string());
  if (arguments_ == nullptr) {
    // Declare 'arguments' variable which exists in all non arrow functions.
    // Note that it might never be accessed, in which case it won't be
    // allocated during variable allocation.
721
    arguments_ = Declare(zone(), ast_value_factory->arguments_string(), VAR);
722
  } else if (IsLexical(arguments_)) {
723 724 725
    // Check if there's lexically declared variable named arguments to avoid
    // redeclaration. See ES#sec-functiondeclarationinstantiation, step 20.
    arguments_ = nullptr;
726 727 728 729 730 731 732
  }
}

void DeclarationScope::DeclareDefaultFunctionVariables(
    AstValueFactory* ast_value_factory) {
  DCHECK(is_function_scope());
  DCHECK(!is_arrow_scope());
733

734
  DeclareThis(ast_value_factory);
735
  new_target_ = Declare(zone(), ast_value_factory->new_target_string(), CONST);
736 737 738

  if (IsConciseMethod(function_kind_) || IsClassConstructor(function_kind_) ||
      IsAccessorFunction(function_kind_)) {
739
    EnsureRareData()->this_function =
740
        Declare(zone(), ast_value_factory->this_function_string(), CONST);
741
  }
742 743
}

744 745 746
Variable* DeclarationScope::DeclareFunctionVar(const AstRawString* name) {
  DCHECK(is_function_scope());
  DCHECK_NULL(function_);
747
  DCHECK_NULL(variables_.Lookup(name));
748 749
  VariableKind kind = is_sloppy(language_mode()) ? SLOPPY_FUNCTION_NAME_VARIABLE
                                                 : NORMAL_VARIABLE;
750 751
  function_ =
      new (zone()) Variable(this, name, CONST, kind, kCreatedInitialized);
752 753 754
  if (calls_sloppy_eval()) {
    NonLocal(name, DYNAMIC);
  } else {
755
    variables_.Add(zone(), function_);
756
  }
757 758
  return function_;
}
759

760 761 762 763 764
Variable* DeclarationScope::DeclareGeneratorObjectVar(
    const AstRawString* name) {
  DCHECK(is_function_scope() || is_module_scope());
  DCHECK_NULL(generator_object_var());

765 766
  Variable* result = EnsureRareData()->generator_object =
      NewTemporary(name, kNotAssigned);
767 768 769 770 771 772 773 774 775 776 777 778
  result->set_is_used();
  return result;
}

Variable* DeclarationScope::DeclarePromiseVar(const AstRawString* name) {
  DCHECK(is_function_scope());
  DCHECK_NULL(promise_var());
  Variable* result = EnsureRareData()->promise = NewTemporary(name);
  result->set_is_used();
  return result;
}

779
bool Scope::HasBeenRemoved() const {
780 781 782 783
  if (sibling() == this) {
    DCHECK_NULL(inner_scope_);
    DCHECK(is_block_scope());
    return true;
784
  }
785
  return false;
786 787 788 789 790 791 792 793 794 795 796
}

Scope* Scope::GetUnremovedScope() {
  Scope* scope = this;
  while (scope != nullptr && scope->HasBeenRemoved()) {
    scope = scope->outer_scope();
  }
  DCHECK_NOT_NULL(scope);
  return scope;
}

797
Scope* Scope::FinalizeBlockScope() {
798
  DCHECK(is_block_scope());
799
  DCHECK(!HasBeenRemoved());
800

801
  if (variables_.occupancy() > 0 ||
802
      (is_declaration_scope() && AsDeclarationScope()->calls_sloppy_eval())) {
803 804
    return this;
  }
805 806

  // Remove this scope from outer scope.
807
  outer_scope()->RemoveInnerScope(this);
808 809

  // Reparent inner scopes.
810 811 812 813 814 815 816 817 818 819
  if (inner_scope_ != nullptr) {
    Scope* scope = inner_scope_;
    scope->outer_scope_ = outer_scope();
    while (scope->sibling_ != nullptr) {
      scope = scope->sibling_;
      scope->outer_scope_ = outer_scope();
    }
    scope->sibling_ = outer_scope()->inner_scope_;
    outer_scope()->inner_scope_ = inner_scope_;
    inner_scope_ = nullptr;
820 821 822
  }

  // Move unresolved variables
823 824 825 826 827 828 829
  if (unresolved_ != nullptr) {
    if (outer_scope()->unresolved_ != nullptr) {
      VariableProxy* unresolved = unresolved_;
      while (unresolved->next_unresolved() != nullptr) {
        unresolved = unresolved->next_unresolved();
      }
      unresolved->set_next_unresolved(outer_scope()->unresolved_);
830 831
    }
    outer_scope()->unresolved_ = unresolved_;
832
    unresolved_ = nullptr;
833 834
  }

835 836
  if (inner_scope_calls_eval_) outer_scope()->inner_scope_calls_eval_ = true;

837 838 839 840 841
  // No need to propagate scope_calls_eval_, since if it was relevant to
  // this scope we would have had to bail out at the top.
  DCHECK(!scope_calls_eval_ || !is_declaration_scope() ||
         !is_sloppy(language_mode()));

842 843
  // This block does not need a context.
  num_heap_slots_ = 0;
844 845 846 847 848 849

  // Mark scope as removed by making it its own sibling.
  sibling_ = this;
  DCHECK(HasBeenRemoved());

  return nullptr;
850 851
}

852 853 854 855 856 857 858
void DeclarationScope::AddLocal(Variable* var) {
  DCHECK(!already_resolved_);
  // Temporaries are only placed in ClosureScopes.
  DCHECK_EQ(GetClosureScope(), this);
  locals_.Add(var);
}

859
Variable* Scope::Declare(Zone* zone, const AstRawString* name,
860 861 862 863 864
                         VariableMode mode, VariableKind kind,
                         InitializationFlag initialization_flag,
                         MaybeAssignedFlag maybe_assigned_flag) {
  bool added;
  Variable* var =
865
      variables_.Declare(zone, this, name, mode, kind, initialization_flag,
866 867 868 869 870
                         maybe_assigned_flag, &added);
  if (added) locals_.Add(var);
  return var;
}

871
void Scope::Snapshot::Reparent(DeclarationScope* new_parent) const {
872 873
  DCHECK_EQ(new_parent, outer_scope_->inner_scope_);
  DCHECK_EQ(new_parent->outer_scope_, outer_scope_);
874
  DCHECK_EQ(new_parent, new_parent->GetClosureScope());
875 876
  DCHECK_NULL(new_parent->inner_scope_);
  DCHECK_NULL(new_parent->unresolved_);
877
  DCHECK(new_parent->locals_.is_empty());
878 879 880 881 882
  Scope* inner_scope = new_parent->sibling_;
  if (inner_scope != top_inner_scope_) {
    for (; inner_scope->sibling() != top_inner_scope_;
         inner_scope = inner_scope->sibling()) {
      inner_scope->outer_scope_ = new_parent;
883 884 885
      if (inner_scope->inner_scope_calls_eval_) {
        new_parent->inner_scope_calls_eval_ = true;
      }
886 887 888
      DCHECK_NE(inner_scope, new_parent);
    }
    inner_scope->outer_scope_ = new_parent;
889 890 891
    if (inner_scope->inner_scope_calls_eval_) {
      new_parent->inner_scope_calls_eval_ = true;
    }
892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908
    new_parent->inner_scope_ = new_parent->sibling_;
    inner_scope->sibling_ = nullptr;
    // Reset the sibling rather than the inner_scope_ since we
    // want to keep new_parent there.
    new_parent->sibling_ = top_inner_scope_;
  }

  if (outer_scope_->unresolved_ != top_unresolved_) {
    VariableProxy* last = outer_scope_->unresolved_;
    while (last->next_unresolved() != top_unresolved_) {
      last = last->next_unresolved();
    }
    last->set_next_unresolved(nullptr);
    new_parent->unresolved_ = outer_scope_->unresolved_;
    outer_scope_->unresolved_ = top_unresolved_;
  }

909 910 911 912 913
  // TODO(verwaest): This currently only moves do-expression declared variables
  // in default arguments that weren't already previously declared with the same
  // name in the closure-scope. See
  // test/mjsunit/harmony/default-parameter-do-expression.js.
  DeclarationScope* outer_closure = outer_scope_->GetClosureScope();
914 915 916

  new_parent->locals_.MoveTail(outer_closure->locals(), top_local_);
  for (Variable* local : new_parent->locals_) {
917 918 919 920 921 922
    DCHECK(local->mode() == TEMPORARY || local->mode() == VAR);
    DCHECK_EQ(local->scope(), local->scope()->GetClosureScope());
    DCHECK_NE(local->scope(), new_parent);
    local->set_scope(new_parent);
    if (local->mode() == VAR) {
      outer_closure->variables_.Remove(local);
923
      new_parent->variables_.Add(new_parent->zone(), local);
924 925
    }
  }
926 927
  outer_closure->locals_.Rewind(top_local_);
  outer_closure->decls_.Rewind(top_decl_);
928 929 930 931

  // Move eval calls since Snapshot's creation into new_parent.
  if (outer_scope_->scope_calls_eval_) {
    new_parent->scope_calls_eval_ = true;
932
    new_parent->inner_scope_calls_eval_ = true;
933 934 935 936
  }
  // Reset the outer_scope's eval state. It will be restored to its
  // original value as necessary in the destructor of this class.
  outer_scope_->scope_calls_eval_ = false;
937
}
938

939 940
void Scope::ReplaceOuterScope(Scope* outer) {
  DCHECK_NOT_NULL(outer);
941
  DCHECK_NOT_NULL(outer_scope_);
942
  DCHECK(!already_resolved_);
943
  outer_scope_->RemoveInnerScope(this);
944 945 946 947
  outer->AddInnerScope(this);
  outer_scope_ = outer;
}

948 949 950 951 952 953 954
Variable* Scope::LookupInScopeInfo(const AstRawString* name) {
  Handle<String> name_handle = name->string();
  // The Scope is backed up by ScopeInfo. This means it cannot operate in a
  // heap-independent mode, and all strings must be internalized immediately. So
  // it's ok to get the Handle<String> here.
  // If we have a serialized scope info, we might find the variable there.
  // There should be no local slot with the given name.
955
  DCHECK_LT(scope_info_->StackSlotIndex(*name_handle), 0);
956

957 958 959 960
  bool found = false;

  VariableLocation location;
  int index;
961 962 963 964
  VariableMode mode;
  InitializationFlag init_flag;
  MaybeAssignedFlag maybe_assigned_flag;

965 966 967 968 969 970 971 972
  {
    location = VariableLocation::CONTEXT;
    index = ScopeInfo::ContextSlotIndex(scope_info_, name_handle, &mode,
                                        &init_flag, &maybe_assigned_flag);
    found = index >= 0;
  }

  if (!found && scope_type() == MODULE_SCOPE) {
973
    location = VariableLocation::MODULE;
974 975
    index = scope_info_->ModuleIndex(name_handle, &mode, &init_flag,
                                     &maybe_assigned_flag);
976
    found = index != 0;
977
  }
978

979
  if (!found) {
980 981 982 983 984 985 986
    index = scope_info_->FunctionContextSlotIndex(*name_handle);
    if (index < 0) return nullptr;  // Nowhere found.
    Variable* var = AsDeclarationScope()->DeclareFunctionVar(name);
    DCHECK_EQ(CONST, var->mode());
    var->AllocateTo(VariableLocation::CONTEXT, index);
    return variables_.Lookup(name);
  }
987

988
  VariableKind kind = NORMAL_VARIABLE;
989 990
  if (location == VariableLocation::CONTEXT &&
      index == scope_info_->ReceiverContextSlotIndex()) {
991
    kind = THIS_VARIABLE;
992 993
  }
  // TODO(marja, rossberg): Correctly declare FUNCTION, CLASS, NEW_TARGET, and
994
  // ARGUMENTS bindings as their corresponding VariableKind.
995 996 997 998 999 1000 1001

  Variable* var = variables_.Declare(zone(), this, name, mode, kind, init_flag,
                                     maybe_assigned_flag);
  var->AllocateTo(location, index);
  return var;
}

1002
Variable* Scope::Lookup(const AstRawString* name) {
1003 1004 1005
  for (Scope* scope = this;
       scope != NULL;
       scope = scope->outer_scope()) {
1006
    Variable* var = scope->LookupLocal(name);
1007 1008 1009 1010 1011
    if (var != NULL) return var;
  }
  return NULL;
}

1012 1013
Variable* DeclarationScope::DeclareParameter(
    const AstRawString* name, VariableMode mode, bool is_optional, bool is_rest,
1014
    bool* is_duplicate, AstValueFactory* ast_value_factory, int position) {
1015
  DCHECK(!already_resolved_);
1016
  DCHECK(is_function_scope() || is_module_scope());
1017
  DCHECK(!has_rest_);
1018
  DCHECK(!is_optional || !is_rest);
1019 1020
  DCHECK(!is_being_lazily_parsed_);
  DCHECK(!was_lazily_parsed_);
1021
  Variable* var;
1022 1023 1024
  if (mode == TEMPORARY) {
    var = NewTemporary(name);
  } else {
1025
    DCHECK_EQ(mode, VAR);
1026
    var = Declare(zone(), name, mode);
1027
    // TODO(wingo): Avoid O(n^2) check.
1028 1029 1030
    if (is_duplicate != nullptr) {
      *is_duplicate = *is_duplicate || IsDeclaredParameter(name);
    }
1031
  }
1032
  has_rest_ = is_rest;
1033
  var->set_initializer_position(position);
1034
  params_.Add(var, zone());
1035 1036 1037
  if (name == ast_value_factory->arguments_string()) {
    has_arguments_parameter_ = true;
  }
1038
  return var;
1039 1040
}

1041
Variable* DeclarationScope::DeclareParameterName(
1042 1043
    const AstRawString* name, bool is_rest, AstValueFactory* ast_value_factory,
    bool declare_as_local, bool add_parameter) {
1044 1045
  DCHECK(!already_resolved_);
  DCHECK(is_function_scope() || is_module_scope());
1046
  DCHECK(!has_rest_ || is_rest);
1047 1048 1049 1050 1051
  DCHECK(is_being_lazily_parsed_);
  has_rest_ = is_rest;
  if (name == ast_value_factory->arguments_string()) {
    has_arguments_parameter_ = true;
  }
1052
  if (FLAG_preparser_scope_analysis) {
1053 1054 1055 1056 1057 1058 1059 1060 1061 1062
    Variable* var;
    if (declare_as_local) {
      var = Declare(zone(), name, VAR);
    } else {
      var = new (zone())
          Variable(this, name, TEMPORARY, NORMAL_VARIABLE, kCreatedInitialized);
    }
    if (add_parameter) {
      params_.Add(var, zone());
    }
1063 1064 1065 1066 1067 1068
    return var;
  }
  DeclareVariableName(name, VAR);
  return nullptr;
}

1069
Variable* Scope::DeclareLocal(const AstRawString* name, VariableMode mode,
1070
                              InitializationFlag init_flag, VariableKind kind,
1071
                              MaybeAssignedFlag maybe_assigned_flag) {
1072
  DCHECK(!already_resolved_);
1073
  // This function handles VAR, LET, and CONST modes.  DYNAMIC variables are
1074
  // introduced during variable allocation, and TEMPORARY variables are
1075
  // allocated via NewTemporary().
1076
  DCHECK(IsDeclaredVariableMode(mode));
1077 1078
  DCHECK_IMPLIES(GetDeclarationScope()->is_being_lazily_parsed(),
                 mode == VAR || mode == LET || mode == CONST);
1079
  DCHECK(!GetDeclarationScope()->was_lazily_parsed());
1080
  return Declare(zone(), name, mode, kind, init_flag, maybe_assigned_flag);
1081 1082
}

marja's avatar
marja committed
1083 1084 1085 1086
Variable* Scope::DeclareVariable(
    Declaration* declaration, VariableMode mode, InitializationFlag init,
    bool allow_harmony_restrictive_generators,
    bool* sloppy_mode_block_scope_function_redefinition, bool* ok) {
1087
  DCHECK(IsDeclaredVariableMode(mode));
marja's avatar
marja committed
1088
  DCHECK(!already_resolved_);
1089 1090
  DCHECK(!GetDeclarationScope()->is_being_lazily_parsed());
  DCHECK(!GetDeclarationScope()->was_lazily_parsed());
marja's avatar
marja committed
1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106

  if (mode == VAR && !is_declaration_scope()) {
    return GetDeclarationScope()->DeclareVariable(
        declaration, mode, init, allow_harmony_restrictive_generators,
        sloppy_mode_block_scope_function_redefinition, ok);
  }
  DCHECK(!is_catch_scope());
  DCHECK(!is_with_scope());
  DCHECK(is_declaration_scope() ||
         (IsLexicalVariableMode(mode) && is_block_scope()));

  VariableProxy* proxy = declaration->proxy();
  DCHECK(proxy->raw_name() != NULL);
  const AstRawString* name = proxy->raw_name();
  bool is_function_declaration = declaration->IsFunctionDeclaration();

1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117
  // Pessimistically assume that top-level variables will be assigned.
  //
  // Top-level variables in a script can be accessed by other scripts or even
  // become global properties. While this does not apply to top-level variables
  // in a module (assuming they are not exported), we must still mark these as
  // assigned because they might be accessed by a lazily parsed top-level
  // function, which, for efficiency, we preparse without variable tracking.
  if (is_script_scope() || is_module_scope()) {
    if (mode != CONST) proxy->set_is_assigned();
  }

marja's avatar
marja committed
1118 1119 1120 1121 1122 1123
  Variable* var = nullptr;
  if (is_eval_scope() && is_sloppy(language_mode()) && mode == VAR) {
    // In a var binding in a sloppy direct eval, pollute the enclosing scope
    // with this new binding by doing the following:
    // The proxy is bound to a lookup variable to force a dynamic declaration
    // using the DeclareEvalVar or DeclareEvalFunction runtime functions.
1124 1125
    var = new (zone())
        Variable(this, name, mode, NORMAL_VARIABLE, init, kMaybeAssigned);
marja's avatar
marja committed
1126 1127 1128 1129 1130 1131
    var->AllocateTo(VariableLocation::LOOKUP, -1);
  } else {
    // Declare the variable in the declaration scope.
    var = LookupLocal(name);
    if (var == NULL) {
      // Declare the name.
1132
      VariableKind kind = NORMAL_VARIABLE;
marja's avatar
marja committed
1133
      if (is_function_declaration) {
1134
        kind = FUNCTION_VARIABLE;
marja's avatar
marja committed
1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149
      }
      var = DeclareLocal(name, mode, init, kind, kNotAssigned);
    } else if (IsLexicalVariableMode(mode) ||
               IsLexicalVariableMode(var->mode())) {
      // Allow duplicate function decls for web compat, see bug 4693.
      bool duplicate_allowed = false;
      if (is_sloppy(language_mode()) && is_function_declaration &&
          var->is_function()) {
        DCHECK(IsLexicalVariableMode(mode) &&
               IsLexicalVariableMode(var->mode()));
        // If the duplication is allowed, then the var will show up
        // in the SloppyBlockFunctionMap and the new FunctionKind
        // will be a permitted duplicate.
        FunctionKind function_kind =
            declaration->AsFunctionDeclaration()->fun()->kind();
1150 1151 1152 1153
        SloppyBlockFunctionMap* map =
            GetDeclarationScope()->sloppy_block_function_map();
        duplicate_allowed = map != nullptr &&
                            map->Lookup(const_cast<AstRawString*>(name),
1154
                                        name->Hash()) != nullptr &&
1155 1156 1157
                            !IsAsyncFunction(function_kind) &&
                            !(allow_harmony_restrictive_generators &&
                              IsGeneratorFunction(function_kind));
marja's avatar
marja committed
1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195
      }
      if (duplicate_allowed) {
        *sloppy_mode_block_scope_function_redefinition = true;
      } else {
        // The name was declared in this scope before; check for conflicting
        // re-declarations. We have a conflict if either of the declarations
        // is not a var (in script scope, we also have to ignore legacy const
        // for compatibility). There is similar code in runtime.cc in the
        // Declare functions. The function CheckConflictingVarDeclarations
        // checks for var and let bindings from different scopes whereas this
        // is a check for conflicting declarations within the same scope. This
        // check also covers the special case
        //
        // function () { let x; { var x; } }
        //
        // because the var declaration is hoisted to the function scope where
        // 'x' is already bound.
        DCHECK(IsDeclaredVariableMode(var->mode()));
        // In harmony we treat re-declarations as early errors. See
        // ES5 16 for a definition of early errors.
        *ok = false;
        return nullptr;
      }
    } else if (mode == VAR) {
      var->set_maybe_assigned();
    }
  }
  DCHECK_NOT_NULL(var);

  // We add a declaration node for every declaration. The compiler
  // will only generate code if necessary. In particular, declarations
  // for inner local variables that do not represent functions won't
  // result in any generated code.
  //
  // This will lead to multiple declaration nodes for the
  // same variable if it is declared several times. This is not a
  // semantic issue, but it may be a performance issue since it may
  // lead to repeated DeclareEvalVar or DeclareEvalFunction calls.
1196
  decls_.Add(declaration);
marja's avatar
marja committed
1197 1198 1199 1200
  proxy->BindTo(var);
  return var;
}

1201 1202
Variable* Scope::DeclareVariableName(const AstRawString* name,
                                     VariableMode mode) {
1203 1204 1205 1206 1207 1208 1209 1210 1211
  DCHECK(IsDeclaredVariableMode(mode));
  DCHECK(!already_resolved_);
  DCHECK(GetDeclarationScope()->is_being_lazily_parsed());

  if (mode == VAR && !is_declaration_scope()) {
    return GetDeclarationScope()->DeclareVariableName(name, mode);
  }
  DCHECK(!is_with_scope());
  DCHECK(!is_eval_scope());
1212 1213 1214 1215 1216 1217
  // Unlike DeclareVariable, DeclareVariableName allows declaring variables in
  // catch scopes: Parser::RewriteCatchPattern bypasses DeclareVariable by
  // calling DeclareLocal directly, and it doesn't make sense to add a similar
  // bypass mechanism for PreParser.
  DCHECK(is_declaration_scope() || (IsLexicalVariableMode(mode) &&
                                    (is_block_scope() || is_catch_scope())));
1218
  DCHECK(scope_info_.is_null());
1219 1220

  // Declare the variable in the declaration scope.
1221
  if (FLAG_preparser_scope_analysis) {
1222
    Variable* var = LookupLocal(name);
1223 1224
    DCHECK_NE(var, kDummyPreParserLexicalVariable);
    DCHECK_NE(var, kDummyPreParserVariable);
1225 1226
    if (var == nullptr) {
      var = DeclareLocal(name, mode);
1227 1228 1229 1230 1231 1232
    } else if (IsLexicalVariableMode(mode) ||
               IsLexicalVariableMode(var->mode())) {
      // Duplicate functions are allowed in the sloppy mode, but if this is not
      // a function declaration, it's an error. This is an error PreParser
      // hasn't previously detected. TODO(marja): Investigate whether we can now
      // start returning this error.
1233
    } else if (mode == VAR) {
1234
      var->set_maybe_assigned();
1235 1236
    }
    var->set_is_used();
1237
    return var;
1238
  } else {
1239
    return variables_.DeclareName(zone(), name, mode);
1240
  }
1241 1242
}

1243 1244 1245 1246 1247 1248 1249
void Scope::AddUnresolved(VariableProxy* proxy) {
  DCHECK(!already_resolved_);
  DCHECK(!proxy->is_resolved());
  proxy->set_next_unresolved(unresolved_);
  unresolved_ = proxy;
}

1250
Variable* DeclarationScope::DeclareDynamicGlobal(const AstRawString* name,
1251
                                                 VariableKind kind) {
1252
  DCHECK(is_script_scope());
1253
  return variables_.Declare(zone(), this, name, DYNAMIC_GLOBAL, kind);
1254
  // TODO(neis): Mark variable as maybe-assigned?
1255 1256 1257
}


1258
bool Scope::RemoveUnresolved(VariableProxy* var) {
1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269
  if (unresolved_ == var) {
    unresolved_ = var->next_unresolved();
    var->set_next_unresolved(nullptr);
    return true;
  }
  VariableProxy* current = unresolved_;
  while (current != nullptr) {
    VariableProxy* next = current->next_unresolved();
    if (var == next) {
      current->set_next_unresolved(next->next_unresolved());
      var->set_next_unresolved(nullptr);
1270
      return true;
1271
    }
1272
    current = next;
1273
  }
1274
  return false;
1275 1276
}

1277
Variable* Scope::NewTemporary(const AstRawString* name) {
1278 1279 1280 1281 1282
  return NewTemporary(name, kMaybeAssigned);
}

Variable* Scope::NewTemporary(const AstRawString* name,
                              MaybeAssignedFlag maybe_assigned) {
1283
  DeclarationScope* scope = GetClosureScope();
1284 1285
  Variable* var = new (zone())
      Variable(scope, name, TEMPORARY, NORMAL_VARIABLE, kCreatedInitialized);
1286
  scope->AddLocal(var);
1287
  if (maybe_assigned == kMaybeAssigned) var->set_maybe_assigned();
1288
  return var;
1289 1290
}

1291
Declaration* Scope::CheckConflictingVarDeclarations() {
1292
  for (Declaration* decl : decls_) {
1293
    VariableMode mode = decl->proxy()->var()->mode();
1294

1295 1296
    // Lexical vs lexical conflicts within the same scope have already been
    // captured in Parser::Declare. The only conflicts we still need to check
1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312
    // are lexical vs nested var, or any declarations within a declaration
    // block scope vs lexical declarations in its surrounding (function) scope.
    Scope* current = this;
    if (decl->IsVariableDeclaration() &&
        decl->AsVariableDeclaration()->AsNested() != nullptr) {
      DCHECK_EQ(mode, VAR);
      current = decl->AsVariableDeclaration()->AsNested()->scope();
    } else if (IsLexicalVariableMode(mode)) {
      if (!is_block_scope()) continue;
      DCHECK(is_declaration_scope());
      DCHECK_EQ(outer_scope()->scope_type(), FUNCTION_SCOPE);
      current = outer_scope();
    }

    // Iterate through all scopes until and including the declaration scope.
    while (true) {
1313
      // There is a conflict if there exists a non-VAR binding.
1314 1315
      Variable* other_var =
          current->variables_.Lookup(decl->proxy()->raw_name());
1316
      if (other_var != nullptr && IsLexicalVariableMode(other_var->mode())) {
1317 1318
        return decl;
      }
1319 1320 1321
      if (current->is_declaration_scope()) break;
      current = current->outer_scope();
    }
1322
  }
1323
  return nullptr;
1324 1325
}

1326 1327 1328 1329 1330 1331 1332 1333 1334
Declaration* Scope::CheckLexDeclarationsConflictingWith(
    const ZoneList<const AstRawString*>& names) {
  DCHECK(is_block_scope());
  for (int i = 0; i < names.length(); ++i) {
    Variable* var = LookupLocal(names.at(i));
    if (var != nullptr) {
      // Conflict; find and return its declaration.
      DCHECK(IsLexicalVariableMode(var->mode()));
      const AstRawString* name = names.at(i);
1335 1336
      for (Declaration* decl : decls_) {
        if (decl->proxy()->raw_name() == name) return decl;
1337 1338 1339 1340 1341 1342
      }
      DCHECK(false);
    }
  }
  return nullptr;
}
1343

1344
void DeclarationScope::AllocateVariables(ParseInfo* info) {
1345
  // Module variables must be allocated before variable resolution
1346
  // to ensure that UpdateNeedsHoleCheck() can detect import variables.
1347 1348
  if (is_module_scope()) AsModuleScope()->AllocateModuleVariables();

1349
  ResolveVariablesRecursively(info);
1350
  AllocateVariablesRecursively();
1351 1352
}

1353 1354 1355 1356 1357 1358 1359 1360 1361
bool Scope::AllowsLazyParsingWithoutUnresolvedVariables(
    const Scope* outer) const {
  // If none of the outer scopes need to decide whether to context allocate
  // specific variables, we can preparse inner functions without unresolved
  // variables. Otherwise we need to find unresolved variables to force context
  // allocation of the matching declarations. We can stop at the outer scope for
  // the parse, since context allocation of those variables is already
  // guaranteed to be correct.
  for (const Scope* s = this; s != outer; s = s->outer_scope_) {
1362 1363 1364 1365
    // Eval forces context allocation on all outer scopes, so we don't need to
    // look at those scopes. Sloppy eval makes top-level non-lexical variables
    // dynamic, whereas strict-mode requires context allocation.
    if (s->is_eval_scope()) return is_sloppy(s->language_mode());
1366 1367 1368 1369
    // Catch scopes force context allocation of all variables.
    if (s->is_catch_scope()) continue;
    // With scopes do not introduce variables that need allocation.
    if (s->is_with_scope()) continue;
1370 1371 1372 1373
    // Module scopes context-allocate all variables, and have no
    // {this} or {arguments} variables whose existence depends on
    // references to them.
    if (s->is_module_scope()) continue;
1374 1375 1376
    // Only block scopes and function scopes should disallow preparsing.
    DCHECK(s->is_block_scope() || s->is_function_scope());
    return false;
1377
  }
1378
  return true;
1379 1380
}

1381 1382 1383
bool DeclarationScope::AllowsLazyCompilation() const {
  return !force_eager_compilation_;
}
1384

1385
int Scope::ContextChainLength(Scope* scope) const {
1386
  int n = 0;
1387
  for (const Scope* s = this; s != scope; s = s->outer_scope_) {
1388
    DCHECK(s != NULL);  // scope must be in the scope chain
1389
    if (s->NeedsContext()) n++;
1390 1391 1392 1393
  }
  return n;
}

1394 1395 1396 1397 1398 1399 1400
int Scope::ContextChainLengthUntilOutermostSloppyEval() const {
  int result = 0;
  int length = 0;

  for (const Scope* s = this; s != nullptr; s = s->outer_scope()) {
    if (!s->NeedsContext()) continue;
    length++;
1401 1402 1403 1404
    if (s->is_declaration_scope() &&
        s->AsDeclarationScope()->calls_sloppy_eval()) {
      result = length;
    }
1405 1406 1407 1408
  }

  return result;
}
1409

1410
DeclarationScope* Scope::GetDeclarationScope() {
1411
  Scope* scope = this;
1412
  while (!scope->is_declaration_scope()) {
1413 1414
    scope = scope->outer_scope();
  }
1415
  return scope->AsDeclarationScope();
1416 1417
}

1418 1419 1420 1421 1422 1423 1424 1425
const DeclarationScope* Scope::GetClosureScope() const {
  const Scope* scope = this;
  while (!scope->is_declaration_scope() || scope->is_block_scope()) {
    scope = scope->outer_scope();
  }
  return scope->AsDeclarationScope();
}

1426
DeclarationScope* Scope::GetClosureScope() {
1427 1428 1429 1430
  Scope* scope = this;
  while (!scope->is_declaration_scope() || scope->is_block_scope()) {
    scope = scope->outer_scope();
  }
1431
  return scope->AsDeclarationScope();
1432 1433
}

1434 1435
bool Scope::NeedsScopeInfo() const {
  DCHECK(!already_resolved_);
1436
  DCHECK(GetClosureScope()->ShouldEagerCompile());
1437 1438 1439 1440 1441 1442
  // The debugger expects all functions to have scope infos.
  // TODO(jochen|yangguo): Remove this requirement.
  if (is_function_scope()) return true;
  return NeedsContext();
}

1443 1444 1445 1446 1447 1448 1449 1450 1451 1452
ModuleScope* Scope::GetModuleScope() {
  Scope* scope = this;
  DCHECK(!scope->is_script_scope());
  while (!scope->is_module_scope()) {
    scope = scope->outer_scope();
    DCHECK_NOT_NULL(scope);
  }
  return scope->AsModuleScope();
}

1453
DeclarationScope* Scope::GetReceiverScope() {
1454
  Scope* scope = this;
1455
  while (!scope->is_script_scope() &&
1456 1457
         (!scope->is_function_scope() ||
          scope->AsDeclarationScope()->is_arrow_scope())) {
1458 1459
    scope = scope->outer_scope();
  }
1460
  return scope->AsDeclarationScope();
1461 1462
}

1463 1464 1465 1466 1467 1468 1469 1470
Scope* Scope::GetOuterScopeWithContext() {
  Scope* scope = outer_scope_;
  while (scope && !scope->NeedsContext()) {
    scope = scope->outer_scope();
  }
  return scope;
}

verwaest's avatar
verwaest committed
1471 1472
Handle<StringSet> DeclarationScope::CollectNonLocals(
    ParseInfo* info, Handle<StringSet> non_locals) {
1473
  VariableProxy* free_variables = FetchFreeVariables(this, info);
verwaest's avatar
verwaest committed
1474
  for (VariableProxy* proxy = free_variables; proxy != nullptr;
1475
       proxy = proxy->next_unresolved()) {
verwaest's avatar
verwaest committed
1476
    non_locals = StringSet::Add(non_locals, proxy->name());
1477
  }
1478
  return non_locals;
1479 1480
}

1481 1482 1483 1484
void DeclarationScope::ResetAfterPreparsing(AstValueFactory* ast_value_factory,
                                            bool aborted) {
  DCHECK(is_function_scope());

1485
  // Reset all non-trivial members.
1486 1487 1488 1489 1490
  if (!aborted || !IsArrowFunction(function_kind_)) {
    // Do not remove parameters when lazy parsing an Arrow Function has failed,
    // as the formal parameters are not re-parsed.
    params_.Clear();
  }
1491
  decls_.Clear();
1492
  locals_.Clear();
1493
  inner_scope_ = nullptr;
1494
  unresolved_ = nullptr;
1495
  sloppy_block_function_map_ = nullptr;
1496
  rare_data_ = nullptr;
1497

1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508
  if (aborted) {
    // Prepare scope for use in the outer zone.
    zone_ = ast_value_factory->zone();
    variables_.Reset(ZoneAllocationPolicy(zone_));
    if (!IsArrowFunction(function_kind_)) {
      DeclareDefaultFunctionVariables(ast_value_factory);
    }
  } else {
    // Make sure this scope isn't used for allocation anymore.
    zone_ = nullptr;
    variables_.Invalidate();
1509
  }
1510 1511 1512

#ifdef DEBUG
  needs_migration_ = false;
1513
  is_being_lazily_parsed_ = false;
1514 1515
#endif

1516
  was_lazily_parsed_ = !aborted;
1517 1518
}

1519
void Scope::SavePreParsedScopeData() {
1520
  DCHECK(FLAG_preparser_scope_analysis);
1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531
  if (ProducedPreParsedScopeData::ScopeIsSkippableFunctionScope(this)) {
    AsDeclarationScope()->SavePreParsedScopeDataForDeclarationScope();
  }

  for (Scope* scope = inner_scope_; scope != nullptr; scope = scope->sibling_) {
    scope->SavePreParsedScopeData();
  }
}

void DeclarationScope::SavePreParsedScopeDataForDeclarationScope() {
  if (produced_preparsed_scope_data_ != nullptr) {
1532
    DCHECK(FLAG_preparser_scope_analysis);
1533 1534 1535 1536 1537
    produced_preparsed_scope_data_->SaveScopeAllocationData(this);
  }
}

void DeclarationScope::AnalyzePartially(AstNodeFactory* ast_node_factory) {
1538 1539 1540
  DCHECK(!force_eager_compilation_);
  VariableProxy* unresolved = nullptr;

1541
  if (!outer_scope_->is_script_scope() || FLAG_preparser_scope_analysis) {
1542 1543 1544
    // Try to resolve unresolved variables for this Scope and migrate those
    // which cannot be resolved inside. It doesn't make sense to try to resolve
    // them in the outer Scopes here, because they are incomplete.
1545 1546
    for (VariableProxy* proxy = FetchFreeVariables(this); proxy != nullptr;
         proxy = proxy->next_unresolved()) {
1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557
      DCHECK(!proxy->is_resolved());
      VariableProxy* copy = ast_node_factory->CopyVariableProxy(proxy);
      copy->set_next_unresolved(unresolved);
      unresolved = copy;
    }

    // Clear arguments_ if unused. This is used as a signal for optimization.
    if (arguments_ != nullptr &&
        !(MustAllocate(arguments_) && !has_arguments_parameter_)) {
      arguments_ = nullptr;
    }
1558

1559 1560 1561 1562 1563
    // Migrate function_ to the right Zone.
    if (function_ != nullptr) {
      function_ = ast_node_factory->CopyVariable(function_);
    }

1564
    if (FLAG_preparser_scope_analysis) {
1565
      SavePreParsedScopeData();
1566
    }
verwaest's avatar
verwaest committed
1567
  }
1568

1569 1570 1571 1572 1573 1574
#ifdef DEBUG
  if (FLAG_print_scopes) {
    PrintF("Inner function scope:\n");
    Print();
  }
#endif
1575

1576
  ResetAfterPreparsing(ast_node_factory->ast_value_factory(), false);
1577 1578

  unresolved_ = unresolved;
1579
}
1580

1581
#ifdef DEBUG
adamk's avatar
adamk committed
1582 1583 1584 1585
namespace {

const char* Header(ScopeType scope_type, FunctionKind function_kind,
                   bool is_declaration_scope) {
1586
  switch (scope_type) {
1587
    case EVAL_SCOPE: return "eval";
1588 1589
    // TODO(adamk): Should we print concise method scopes specially?
    case FUNCTION_SCOPE:
1590 1591 1592 1593
      if (IsGeneratorFunction(function_kind)) return "function*";
      if (IsAsyncFunction(function_kind)) return "async function";
      if (IsArrowFunction(function_kind)) return "arrow";
      return "function";
1594
    case MODULE_SCOPE: return "module";
1595
    case SCRIPT_SCOPE: return "global";
1596
    case CATCH_SCOPE: return "catch";
1597
    case BLOCK_SCOPE: return is_declaration_scope ? "varblock" : "block";
1598
    case WITH_SCOPE: return "with";
1599 1600 1601 1602
  }
  UNREACHABLE();
}

adamk's avatar
adamk committed
1603
void Indent(int n, const char* str) { PrintF("%*s%s", n, "", str); }
1604

adamk's avatar
adamk committed
1605
void PrintName(const AstRawString* name) {
1606
  PrintF("%.*s", name->length(), name->raw_data());
1607 1608
}

adamk's avatar
adamk committed
1609
void PrintLocation(Variable* var) {
1610
  switch (var->location()) {
1611
    case VariableLocation::UNALLOCATED:
1612
      break;
1613
    case VariableLocation::PARAMETER:
1614 1615
      PrintF("parameter[%d]", var->index());
      break;
1616
    case VariableLocation::LOCAL:
1617 1618
      PrintF("local[%d]", var->index());
      break;
1619
    case VariableLocation::CONTEXT:
1620 1621
      PrintF("context[%d]", var->index());
      break;
1622
    case VariableLocation::LOOKUP:
1623 1624
      PrintF("lookup");
      break;
1625 1626 1627
    case VariableLocation::MODULE:
      PrintF("module");
      break;
1628 1629 1630
  }
}

adamk's avatar
adamk committed
1631 1632 1633 1634 1635 1636 1637
void PrintVar(int indent, Variable* var) {
  Indent(indent, VariableMode2String(var->mode()));
  PrintF(" ");
  if (var->raw_name()->IsEmpty())
    PrintF(".%p", reinterpret_cast<void*>(var));
  else
    PrintName(var->raw_name());
1638
  PrintF(";  // (%p) ", reinterpret_cast<void*>(var));
adamk's avatar
adamk committed
1639 1640 1641 1642 1643 1644 1645 1646 1647 1648
  PrintLocation(var);
  bool comma = !var->IsUnallocated();
  if (var->has_forced_context_allocation()) {
    if (comma) PrintF(", ");
    PrintF("forced context allocation");
    comma = true;
  }
  if (var->maybe_assigned() == kNotAssigned) {
    if (comma) PrintF(", ");
    PrintF("never assigned");
1649 1650 1651 1652 1653 1654
    comma = true;
  }
  if (var->initialization_flag() == kNeedsInitialization &&
      !var->binding_needs_init()) {
    if (comma) PrintF(", ");
    PrintF("hole initialization elided");
1655
  }
adamk's avatar
adamk committed
1656
  PrintF("\n");
1657 1658
}

adamk's avatar
adamk committed
1659 1660 1661
void PrintMap(int indent, const char* label, VariableMap* map, bool locals,
              Variable* function_var) {
  bool printed_label = false;
1662
  for (VariableMap::Entry* p = map->Start(); p != nullptr; p = map->Next(p)) {
1663
    Variable* var = reinterpret_cast<Variable*>(p->value);
adamk's avatar
adamk committed
1664
    if (var == function_var) continue;
1665 1666 1667 1668
    if (var == kDummyPreParserVariable ||
        var == kDummyPreParserLexicalVariable) {
      continue;
    }
1669
    bool local = !IsDynamicVariableMode(var->mode());
adamk's avatar
adamk committed
1670 1671 1672 1673 1674
    if ((locals ? local : !local) &&
        (var->is_used() || !var->IsUnallocated())) {
      if (!printed_label) {
        Indent(indent, label);
        printed_label = true;
1675
      }
adamk's avatar
adamk committed
1676
      PrintVar(indent, var);
1677
    }
1678 1679 1680
  }
}

adamk's avatar
adamk committed
1681 1682
}  // anonymous namespace

1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694
void DeclarationScope::PrintParameters() {
  PrintF(" (");
  for (int i = 0; i < params_.length(); i++) {
    if (i > 0) PrintF(", ");
    const AstRawString* name = params_[i]->raw_name();
    if (name->IsEmpty())
      PrintF(".%p", reinterpret_cast<void*>(params_[i]));
    else
      PrintName(name);
  }
  PrintF(")");
}
1695

1696 1697 1698 1699 1700
void Scope::Print(int n) {
  int n0 = (n > 0 ? n : 0);
  int n1 = n0 + 2;  // indentation

  // Print header.
1701 1702 1703 1704
  FunctionKind function_kind = is_function_scope()
                                   ? AsDeclarationScope()->function_kind()
                                   : kNormalFunction;
  Indent(n0, Header(scope_type_, function_kind, is_declaration_scope()));
1705
  if (scope_name_ != nullptr && !scope_name_->IsEmpty()) {
1706 1707 1708 1709 1710
    PrintF(" ");
    PrintName(scope_name_);
  }

  // Print parameters, if any.
1711
  Variable* function = nullptr;
1712
  if (is_function_scope()) {
1713
    AsDeclarationScope()->PrintParameters();
1714
    function = AsDeclarationScope()->function_var();
1715 1716
  }

1717 1718
  PrintF(" { // (%p) (%d, %d)\n", reinterpret_cast<void*>(this),
         start_position(), end_position());
1719 1720 1721
  if (is_hidden()) {
    Indent(n1, "// is hidden\n");
  }
1722 1723

  // Function name, if any (named function literals, only).
1724
  if (function != nullptr) {
1725
    Indent(n1, "// (local) function name: ");
1726
    PrintName(function->raw_name());
1727 1728 1729 1730
    PrintF("\n");
  }

  // Scope info.
1731
  if (is_strict(language_mode())) {
1732
    Indent(n1, "// strict mode scope\n");
1733
  }
1734
  if (IsAsmModule()) Indent(n1, "// scope is an asm module\n");
1735 1736 1737
  if (is_declaration_scope() && AsDeclarationScope()->calls_sloppy_eval()) {
    Indent(n1, "// scope calls sloppy 'eval'\n");
  }
1738
  if (is_declaration_scope() && AsDeclarationScope()->uses_super_property()) {
1739
    Indent(n1, "// scope uses 'super' property\n");
1740
  }
1741
  if (inner_scope_calls_eval_) Indent(n1, "// inner scope calls 'eval'\n");
1742 1743
  if (is_declaration_scope()) {
    DeclarationScope* scope = AsDeclarationScope();
1744
    if (scope->was_lazily_parsed()) Indent(n1, "// lazily parsed\n");
1745 1746
    if (scope->ShouldEagerCompile()) Indent(n1, "// will be compiled\n");
  }
1747 1748 1749
  if (has_forced_context_allocation()) {
    Indent(n1, "// forces context allocation\n");
  }
1750 1751 1752 1753 1754 1755
  if (num_stack_slots_ > 0) {
    Indent(n1, "// ");
    PrintF("%d stack slots\n", num_stack_slots_);
  }
  if (num_heap_slots_ > 0) {
    Indent(n1, "// ");
1756
    PrintF("%d heap slots\n", num_heap_slots_);
1757
  }
1758 1759

  // Print locals.
1760
  if (function != nullptr) {
1761
    Indent(n1, "// function var:\n");
1762
    PrintVar(n1, function);
1763 1764
  }

1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777
  // Print temporaries.
  {
    bool printed_header = false;
    for (Variable* local : locals_) {
      if (local->mode() != TEMPORARY) continue;
      if (!printed_header) {
        printed_header = true;
        Indent(n1, "// temporary vars:\n");
      }
      PrintVar(n1, local);
    }
  }

1778 1779 1780 1781
  if (variables_.occupancy() > 0) {
    PrintMap(n1, "// local vars:\n", &variables_, true, function);
    PrintMap(n1, "// dynamic vars:\n", &variables_, false, function);
  }
1782 1783 1784

  // Print inner scopes (disable by providing negative n).
  if (n >= 0) {
1785 1786
    for (Scope* scope = inner_scope_; scope != nullptr;
         scope = scope->sibling_) {
1787
      PrintF("\n");
1788
      scope->Print(n1);
1789 1790 1791 1792 1793
    }
  }

  Indent(n0, "}\n");
}
1794 1795

void Scope::CheckScopePositions() {
jwolfe's avatar
jwolfe committed
1796
  // Visible leaf scopes must have real positions.
1797
  if (!is_hidden() && inner_scope_ == nullptr) {
yangguo's avatar
yangguo committed
1798 1799
    CHECK_NE(kNoSourcePosition, start_position());
    CHECK_NE(kNoSourcePosition, end_position());
1800
  }
1801 1802 1803
  for (Scope* scope = inner_scope_; scope != nullptr; scope = scope->sibling_) {
    scope->CheckScopePositions();
  }
1804
}
1805 1806

void Scope::CheckZones() {
1807
  DCHECK(!needs_migration_);
1808
  for (Scope* scope = inner_scope_; scope != nullptr; scope = scope->sibling_) {
1809
    if (scope->is_declaration_scope() &&
1810
        scope->AsDeclarationScope()->was_lazily_parsed()) {
1811 1812 1813 1814
      DCHECK_NULL(scope->zone());
      DCHECK_NULL(scope->inner_scope_);
      continue;
    }
marja's avatar
marja committed
1815
    scope->CheckZones();
1816 1817
  }
}
1818 1819
#endif  // DEBUG

1820
Variable* Scope::NonLocal(const AstRawString* name, VariableMode mode) {
1821 1822
  // Declare a new non-local.
  DCHECK(IsDynamicVariableMode(mode));
1823
  Variable* var = variables_.Declare(zone(), nullptr, name, mode);
1824 1825
  // Allocate it by giving it a dynamic lookup.
  var->AllocateTo(VariableLocation::LOOKUP, -1);
1826 1827 1828
  return var;
}

1829
Variable* Scope::LookupRecursive(VariableProxy* proxy, Scope* outer_scope_end) {
verwaest's avatar
verwaest committed
1830
  DCHECK_NE(outer_scope_end, this);
1831 1832 1833 1834 1835 1836 1837
  // Short-cut: whenever we find a debug-evaluate scope, just look everything up
  // dynamically. Debug-evaluate doesn't properly create scope info for the
  // lookups it does. It may not have a valid 'this' declaration, and anything
  // accessed through debug-evaluate might invalidly resolve to stack-allocated
  // variables.
  // TODO(yangguo): Remove once debug-evaluate creates proper ScopeInfo for the
  // scopes in which it's evaluating.
1838
  if (is_debug_evaluate_scope_) return NonLocal(proxy->raw_name(), DYNAMIC);
1839

1840
  // Try to find the variable in this scope.
1841
  Variable* var = LookupLocal(proxy->raw_name());
1842

verwaest's avatar
verwaest committed
1843 1844 1845
  // We found a variable and we are done. (Even if there is an 'eval' in this
  // scope which introduces the same variable again, the resulting variable
  // remains the same.)
1846
  if (var != nullptr) return var;
1847

1848
  if (outer_scope_ == outer_scope_end) {
1849 1850 1851
    // We may just be trying to find all free variables. In that case, don't
    // declare them in the outer scope.
    if (!is_script_scope()) return nullptr;
1852 1853
    // No binding has been found. Declare a variable on the global object.
    return AsDeclarationScope()->DeclareDynamicGlobal(proxy->raw_name(),
1854
                                                      NORMAL_VARIABLE);
1855 1856 1857 1858
  }

  DCHECK(!is_script_scope());

1859
  var = outer_scope_->LookupRecursive(proxy, outer_scope_end);
1860 1861 1862 1863

  // The variable could not be resolved statically.
  if (var == nullptr) return var;

1864
  // TODO(marja): Separate LookupRecursive for preparsed scopes better.
1865
  if (var == kDummyPreParserVariable || var == kDummyPreParserLexicalVariable) {
1866 1867 1868 1869 1870
    DCHECK(GetDeclarationScope()->is_being_lazily_parsed());
    DCHECK(FLAG_lazy_inner_functions);
    return var;
  }

1871 1872 1873 1874 1875 1876 1877 1878 1879 1880 1881 1882 1883 1884 1885 1886 1887 1888
  if (is_function_scope() && !var->is_dynamic()) {
    var->ForceContextAllocation();
  }
  // "this" can't be shadowed by "eval"-introduced bindings or by "with"
  // scopes.
  // TODO(wingo): There are other variables in this category; add them.
  if (var->is_this()) return var;

  if (is_with_scope()) {
    // The current scope is a with scope, so the variable binding can not be
    // statically resolved. However, note that it was necessary to do a lookup
    // in the outer scope anyway, because if a binding exists in an outer
    // scope, the associated variable has to be marked as potentially being
    // accessed from inside of an inner with scope (the property may not be in
    // the 'with' object).
    if (!var->is_dynamic() && var->IsUnallocated()) {
      DCHECK(!already_resolved_);
      var->set_is_used();
1889
      var->ForceContextAllocation();
1890
      if (proxy->is_assigned()) var->set_maybe_assigned();
1891
    }
1892
    return NonLocal(proxy->raw_name(), DYNAMIC);
verwaest's avatar
verwaest committed
1893 1894
  }

1895
  if (is_declaration_scope() && AsDeclarationScope()->calls_sloppy_eval()) {
1896
    // A variable binding may have been found in an outer scope, but the current
verwaest's avatar
verwaest committed
1897 1898 1899 1900 1901 1902
    // scope makes a sloppy 'eval' call, so the found variable may not be the
    // correct one (the 'eval' may introduce a binding with the same name). In
    // that case, change the lookup result to reflect this situation. Only
    // scopes that can host var bindings (declaration scopes) need be considered
    // here (this excludes block and catch scopes), and variable lookups at
    // script scope are always dynamic.
1903 1904
    if (var->IsGlobalObjectProperty()) {
      return NonLocal(proxy->raw_name(), DYNAMIC_GLOBAL);
1905
    }
1906 1907 1908 1909 1910 1911

    if (var->is_dynamic()) return var;

    Variable* invalidated = var;
    var = NonLocal(proxy->raw_name(), DYNAMIC_LOCAL);
    var->set_local_if_not_shadowed(invalidated);
1912
  }
verwaest's avatar
verwaest committed
1913

1914 1915 1916
  return var;
}

1917
void Scope::ResolveVariable(ParseInfo* info, VariableProxy* proxy) {
1918
  DCHECK(info->script_scope()->is_script_scope());
1919
  DCHECK(!proxy->is_resolved());
1920
  Variable* var = LookupRecursive(proxy, nullptr);
1921
  ResolveTo(info, proxy, var);
verwaest's avatar
verwaest committed
1922 1923
}

1924 1925
namespace {

1926 1927 1928 1929 1930 1931
void SetNeedsHoleCheck(Variable* var, VariableProxy* proxy) {
  proxy->set_needs_hole_check();
  var->ForceHoleInitialization();
}

void UpdateNeedsHoleCheck(Variable* var, VariableProxy* proxy, Scope* scope) {
1932 1933 1934 1935 1936
  if (var->mode() == DYNAMIC_LOCAL) {
    // Dynamically introduced variables never need a hole check (since they're
    // VAR bindings, either from var or function declarations), but the variable
    // they shadow might need a hole check, which we want to do if we decide
    // that no shadowing variable was dynamically introoduced.
1937 1938
    DCHECK_EQ(kCreatedInitialized, var->initialization_flag());
    return UpdateNeedsHoleCheck(var->local_if_not_shadowed(), proxy, scope);
1939 1940
  }

1941
  if (var->initialization_flag() == kCreatedInitialized) return;
1942 1943 1944 1945 1946

  // It's impossible to eliminate module import hole checks here, because it's
  // unknown at compilation time whether the binding referred to in the
  // exporting module itself requires hole checks.
  if (var->location() == VariableLocation::MODULE && !var->IsExport()) {
1947
    return SetNeedsHoleCheck(var, proxy);
1948 1949 1950 1951 1952 1953 1954 1955 1956 1957
  }

  // Check if the binding really needs an initialization check. The check
  // can be skipped in the following situation: we have a LET or CONST
  // binding, both the Variable and the VariableProxy have the same
  // declaration scope (i.e. they are both in global code, in the
  // same function or in the same eval code), the VariableProxy is in
  // the source physically located after the initializer of the variable,
  // and that the initializer cannot be skipped due to a nonlinear scope.
  //
1958
  // The condition on the closure scopes is a conservative check for
1959 1960 1961 1962 1963 1964 1965 1966 1967
  // nested functions that access a binding and are called before the
  // binding is initialized:
  //   function() { f(); let x = 1; function f() { x = 2; } }
  //
  // The check cannot be skipped on non-linear scopes, namely switch
  // scopes, to ensure tests are done in cases like the following:
  //   switch (1) { case 0: let x = 2; case 1: f(x); }
  // The scope of the variable needs to be checked, in case the use is
  // in a sub-block which may be linear.
1968
  if (var->scope()->GetClosureScope() != scope->GetClosureScope()) {
1969
    return SetNeedsHoleCheck(var, proxy);
1970 1971 1972
  }

  if (var->is_this()) {
1973
    DCHECK(IsDerivedConstructor(scope->GetClosureScope()->function_kind()));
1974
    // TODO(littledan): implement 'this' hole check elimination.
1975
    return SetNeedsHoleCheck(var, proxy);
1976 1977 1978 1979 1980 1981
  }

  // We should always have valid source positions.
  DCHECK(var->initializer_position() != kNoSourcePosition);
  DCHECK(proxy->position() != kNoSourcePosition);

1982 1983 1984 1985
  if (var->scope()->is_nonlinear() ||
      var->initializer_position() >= proxy->position()) {
    return SetNeedsHoleCheck(var, proxy);
  }
1986 1987 1988 1989
}

}  // anonymous namespace

1990
void Scope::ResolveTo(ParseInfo* info, VariableProxy* proxy, Variable* var) {
1991
#ifdef DEBUG
1992
  if (info->is_native()) {
1993 1994 1995 1996
    // To avoid polluting the global object in native scripts
    //  - Variables must not be allocated to the global scope.
    CHECK_NOT_NULL(outer_scope());
    //  - Variables must be bound locally or unallocated.
1997
    if (var->IsGlobalObjectProperty()) {
1998 1999 2000 2001 2002 2003
      // The following variable name may be minified. If so, disable
      // minification in js2c.py for better output.
      Handle<String> name = proxy->raw_name()->string();
      V8_Fatal(__FILE__, __LINE__, "Unbound variable: '%s' in native script.",
               name->ToCString().get());
    }
2004 2005 2006 2007 2008 2009 2010 2011
    VariableLocation location = var->location();
    CHECK(location == VariableLocation::LOCAL ||
          location == VariableLocation::CONTEXT ||
          location == VariableLocation::PARAMETER ||
          location == VariableLocation::UNALLOCATED);
  }
#endif

2012
  DCHECK_NOT_NULL(var);
2013
  UpdateNeedsHoleCheck(var, proxy, this);
2014
  proxy->BindTo(var);
2015 2016
}

2017
void Scope::ResolveVariablesRecursively(ParseInfo* info) {
2018
  DCHECK(info->script_scope()->is_script_scope());
2019 2020 2021
  // Lazy parsed declaration scopes are already partially analyzed. If there are
  // unresolved references remaining, they just need to be resolved in outer
  // scopes.
2022
  if (is_declaration_scope() && AsDeclarationScope()->was_lazily_parsed()) {
2023 2024 2025 2026 2027 2028 2029 2030 2031 2032 2033 2034 2035 2036 2037 2038
    DCHECK(variables_.occupancy() == 0);
    for (VariableProxy* proxy = unresolved_; proxy != nullptr;
         proxy = proxy->next_unresolved()) {
      Variable* var = outer_scope()->LookupRecursive(proxy, nullptr);
      if (!var->is_dynamic()) {
        var->set_is_used();
        var->ForceContextAllocation();
        if (proxy->is_assigned()) var->set_maybe_assigned();
      }
    }
  } else {
    // Resolve unresolved variables for this scope.
    for (VariableProxy* proxy = unresolved_; proxy != nullptr;
         proxy = proxy->next_unresolved()) {
      ResolveVariable(info, proxy);
    }
2039

2040 2041 2042 2043 2044
    // Resolve unresolved variables for inner scopes.
    for (Scope* scope = inner_scope_; scope != nullptr;
         scope = scope->sibling_) {
      scope->ResolveVariablesRecursively(info);
    }
2045 2046 2047
  }
}

verwaest's avatar
verwaest committed
2048
VariableProxy* Scope::FetchFreeVariables(DeclarationScope* max_outer_scope,
2049
                                         ParseInfo* info,
verwaest's avatar
verwaest committed
2050
                                         VariableProxy* stack) {
2051
  // Module variables must be allocated before variable resolution
2052
  // to ensure that UpdateNeedsHoleCheck() can detect import variables.
2053 2054 2055
  if (info != nullptr && is_module_scope()) {
    AsModuleScope()->AllocateModuleVariables();
  }
2056 2057 2058 2059
  // Lazy parsed declaration scopes are already partially analyzed. If there are
  // unresolved references remaining, they just need to be resolved in outer
  // scopes.
  Scope* lookup =
2060
      is_declaration_scope() && AsDeclarationScope()->was_lazily_parsed()
2061 2062
          ? outer_scope()
          : this;
2063 2064 2065
  for (VariableProxy *proxy = unresolved_, *next = nullptr; proxy != nullptr;
       proxy = next) {
    next = proxy->next_unresolved();
2066
    DCHECK(!proxy->is_resolved());
2067 2068
    Variable* var =
        lookup->LookupRecursive(proxy, max_outer_scope->outer_scope());
verwaest's avatar
verwaest committed
2069 2070 2071
    if (var == nullptr) {
      proxy->set_next_unresolved(stack);
      stack = proxy;
2072 2073
    } else if (var != kDummyPreParserVariable &&
               var != kDummyPreParserLexicalVariable) {
2074 2075 2076 2077 2078 2079 2080 2081
      if (info != nullptr) {
        // In this case we need to leave scopes in a way that they can be
        // allocated. If we resolved variables from lazy parsed scopes, we need
        // to context allocate the var.
        ResolveTo(info, proxy, var);
        if (!var->is_dynamic() && lookup != this) var->ForceContextAllocation();
      } else {
        var->set_is_used();
2082 2083 2084
        if (proxy->is_assigned()) {
          var->set_maybe_assigned();
        }
2085
      }
2086 2087 2088
    }
  }

verwaest's avatar
verwaest committed
2089 2090 2091
  // Clear unresolved_ as it's in an inconsistent state.
  unresolved_ = nullptr;

2092
  for (Scope* scope = inner_scope_; scope != nullptr; scope = scope->sibling_) {
2093
    stack = scope->FetchFreeVariables(max_outer_scope, info, stack);
2094
  }
verwaest's avatar
verwaest committed
2095 2096

  return stack;
2097
}
2098 2099

bool Scope::MustAllocate(Variable* var) {
2100 2101 2102
  if (var == kDummyPreParserLexicalVariable || var == kDummyPreParserVariable) {
    return true;
  }
2103
  DCHECK(var->location() != VariableLocation::MODULE);
2104 2105 2106
  // Give var a read/write use if there is a chance it might be accessed
  // via an eval() call.  This is only possible if the variable has a
  // visible name.
2107
  if ((var->is_this() || !var->raw_name()->IsEmpty()) &&
2108
      (inner_scope_calls_eval_ || is_catch_scope() || is_script_scope())) {
2109
    var->set_is_used();
2110
    if (inner_scope_calls_eval_) var->set_maybe_assigned();
2111
  }
2112
  DCHECK(!var->has_forced_context_allocation() || var->is_used());
2113
  // Global variables do not need to be allocated.
2114
  return !var->IsGlobalObjectProperty() && var->is_used();
2115 2116 2117 2118
}


bool Scope::MustAllocateInContext(Variable* var) {
2119 2120 2121
  // If var is accessed from an inner scope, or if there is a possibility
  // that it might be accessed from the current or an inner scope (through
  // an eval() call or a runtime with lookup), it must be allocated in the
2122
  // context.
2123
  //
2124 2125 2126 2127 2128
  // Exceptions: If the scope as a whole has forced context allocation, all
  // variables will have context allocation, even temporaries.  Otherwise
  // temporary variables are always stack-allocated.  Catch-bound variables are
  // always context-allocated.
  if (has_forced_context_allocation()) return true;
2129
  if (var->mode() == TEMPORARY) return false;
2130
  if (is_catch_scope()) return true;
2131 2132 2133 2134
  if ((is_script_scope() || is_eval_scope()) &&
      IsLexicalVariableMode(var->mode())) {
    return true;
  }
2135
  return var->has_forced_context_allocation() || inner_scope_calls_eval_;
2136 2137 2138 2139
}


void Scope::AllocateStackSlot(Variable* var) {
2140
  if (is_block_scope()) {
2141
    outer_scope()->GetDeclarationScope()->AllocateStackSlot(var);
2142
  } else {
2143
    var->AllocateTo(VariableLocation::LOCAL, num_stack_slots_++);
2144
  }
2145 2146 2147 2148
}


void Scope::AllocateHeapSlot(Variable* var) {
2149
  var->AllocateTo(VariableLocation::CONTEXT, num_heap_slots_++);
2150 2151
}

2152
void DeclarationScope::AllocateParameterLocals() {
2153
  DCHECK(is_function_scope());
2154

2155
  bool uses_sloppy_arguments = false;
2156

2157
  if (arguments_ != nullptr) {
2158
    DCHECK(!is_arrow_scope());
2159
    // 'arguments' is used. Unless there is also a parameter called
2160 2161 2162 2163 2164 2165 2166
    // 'arguments', we must be conservative and allocate all parameters to
    // the context assuming they will be captured by the arguments object.
    // If we have a parameter named 'arguments', a (new) value is always
    // assigned to it via the function invocation. Then 'arguments' denotes
    // that specific parameter value and cannot be used to access the
    // parameters, which is why we don't need to allocate an arguments
    // object in that case.
2167
    if (MustAllocate(arguments_) && !has_arguments_parameter_) {
2168 2169 2170 2171 2172 2173 2174 2175 2176 2177 2178
      // In strict mode 'arguments' does not alias formal parameters.
      // Therefore in strict mode we allocate parameters as if 'arguments'
      // were not used.
      // If the parameter list is not simple, arguments isn't sloppy either.
      uses_sloppy_arguments =
          is_sloppy(language_mode()) && has_simple_parameters();
    } else {
      // 'arguments' is unused. Tell the code generator that it does not need to
      // allocate the arguments object by nulling out arguments_.
      arguments_ = nullptr;
    }
2179 2180 2181 2182 2183 2184
  }

  // The same parameter may occur multiple times in the parameters_ list.
  // If it does, and if it is not copied into the context object, it must
  // receive the highest parameter index for that parameter; thus iteration
  // order is relevant!
2185
  for (int i = num_parameters() - 1; i >= 0; --i) {
2186
    Variable* var = params_[i];
2187
    DCHECK(!has_rest_ || var != rest_parameter());
2188
    DCHECK_EQ(this, var->scope());
2189
    if (uses_sloppy_arguments) {
2190
      var->set_is_used();
2191
      var->set_maybe_assigned();
2192
      var->ForceContextAllocation();
2193
    }
2194
    AllocateParameter(var, i);
2195 2196
  }
}
2197

2198
void DeclarationScope::AllocateParameter(Variable* var, int index) {
2199
  if (MustAllocate(var)) {
2200 2201
    if (has_forced_context_allocation_for_parameters() ||
        MustAllocateInContext(var)) {
2202 2203 2204 2205 2206 2207 2208
      DCHECK(var->IsUnallocated() || var->IsContextSlot());
      if (var->IsUnallocated()) {
        AllocateHeapSlot(var);
      }
    } else {
      DCHECK(var->IsUnallocated() || var->IsParameter());
      if (var->IsUnallocated()) {
2209
        var->AllocateTo(VariableLocation::PARAMETER, index);
2210 2211 2212 2213 2214
      }
    }
  }
}

2215 2216
void DeclarationScope::AllocateReceiver() {
  if (!has_this_declaration()) return;
2217 2218 2219 2220 2221
  DCHECK_NOT_NULL(receiver());
  DCHECK_EQ(receiver()->scope(), this);
  AllocateParameter(receiver(), -1);
}

2222
void Scope::AllocateNonParameterLocal(Variable* var) {
2223
  DCHECK(var->scope() == this);
2224
  if (var->IsUnallocated() && MustAllocate(var)) {
2225 2226 2227 2228 2229 2230 2231 2232
    if (MustAllocateInContext(var)) {
      AllocateHeapSlot(var);
    } else {
      AllocateStackSlot(var);
    }
  }
}

2233
void Scope::AllocateNonParameterLocalsAndDeclaredGlobals() {
2234 2235
  for (Variable* local : locals_) {
    AllocateNonParameterLocal(local);
2236 2237
  }

2238
  if (is_declaration_scope()) {
2239
    AsDeclarationScope()->AllocateLocals();
2240 2241 2242
  }
}

2243
void DeclarationScope::AllocateLocals() {
2244 2245 2246
  // For now, function_ must be allocated at the very end.  If it gets
  // allocated in the context, it must be the last slot in the context,
  // because of the current ScopeInfo implementation (see
2247
  // ScopeInfo::ScopeInfo(FunctionScope* scope) constructor).
2248
  if (function_ != nullptr) {
2249
    AllocateNonParameterLocal(function_);
2250
  }
2251

2252
  DCHECK(!has_rest_ || !MustAllocate(rest_parameter()) ||
2253
         !rest_parameter()->IsUnallocated());
2254

2255 2256
  if (new_target_ != nullptr && !MustAllocate(new_target_)) {
    new_target_ = nullptr;
2257 2258
  }

2259 2260
  NullifyRareVariableIf(RareVariable::kThisFunction,
                        [=](Variable* var) { return !MustAllocate(var); });
2261 2262
}

2263 2264 2265
void ModuleScope::AllocateModuleVariables() {
  for (const auto& it : module()->regular_imports()) {
    Variable* var = LookupLocal(it.first);
2266 2267
    var->AllocateTo(VariableLocation::MODULE, it.second->cell_index);
    DCHECK(!var->IsExport());
2268 2269
  }

2270 2271
  for (const auto& it : module()->regular_exports()) {
    Variable* var = LookupLocal(it.first);
2272 2273
    var->AllocateTo(VariableLocation::MODULE, it.second->cell_index);
    DCHECK(var->IsExport());
2274 2275 2276
  }
}

2277
void Scope::AllocateVariablesRecursively() {
2278
  DCHECK(!already_resolved_);
2279
  DCHECK_IMPLIES(!FLAG_preparser_scope_analysis, num_stack_slots_ == 0);
2280

2281
  // Don't allocate variables of preparsed scopes.
2282
  if (is_declaration_scope() && AsDeclarationScope()->was_lazily_parsed()) {
2283 2284
    return;
  }
2285

2286
  // Allocate variables for inner scopes.
2287
  for (Scope* scope = inner_scope_; scope != nullptr; scope = scope->sibling_) {
2288
    scope->AllocateVariablesRecursively();
2289 2290
  }

2291 2292
  DCHECK(!already_resolved_);
  DCHECK_EQ(Context::MIN_CONTEXT_SLOTS, num_heap_slots_);
2293

2294 2295
  // Allocate variables for this scope.
  // Parameters must be allocated first, if any.
2296
  if (is_declaration_scope()) {
2297
    if (is_function_scope()) {
2298 2299
      AsDeclarationScope()->AllocateParameterLocals();
    }
2300 2301
    AsDeclarationScope()->AllocateReceiver();
  }
2302
  AllocateNonParameterLocalsAndDeclaredGlobals();
2303

2304 2305 2306
  // Force allocation of a context for this scope if necessary. For a 'with'
  // scope and for a function scope that makes an 'eval' call we need a context,
  // even if no local variables were statically allocated in the scope.
2307
  // Likewise for modules and function scopes representing asm.js modules.
2308
  bool must_have_context =
2309
      is_with_scope() || is_module_scope() || IsAsmModule() ||
2310 2311 2312
      (is_function_scope() && AsDeclarationScope()->calls_sloppy_eval()) ||
      (is_block_scope() && is_declaration_scope() &&
       AsDeclarationScope()->calls_sloppy_eval());
2313 2314

  // If we didn't allocate any locals in the local context, then we only
2315 2316
  // need the minimal number of slots if we must have a context.
  if (num_heap_slots_ == Context::MIN_CONTEXT_SLOTS && !must_have_context) {
2317 2318 2319 2320
    num_heap_slots_ = 0;
  }

  // Allocation done.
2321
  DCHECK(num_heap_slots_ == 0 || num_heap_slots_ >= Context::MIN_CONTEXT_SLOTS);
2322 2323
}

2324
void Scope::AllocateScopeInfosRecursively(Isolate* isolate,
jochen's avatar
jochen committed
2325
                                          MaybeHandle<ScopeInfo> outer_scope) {
2326
  DCHECK(scope_info_.is_null());
2327 2328 2329
  MaybeHandle<ScopeInfo> next_outer_scope = outer_scope;

  if (NeedsScopeInfo()) {
jochen's avatar
jochen committed
2330
    scope_info_ = ScopeInfo::Create(isolate, zone(), this, outer_scope);
2331 2332 2333
    // The ScopeInfo chain should mirror the context chain, so we only link to
    // the next outer scope that needs a context.
    if (NeedsContext()) next_outer_scope = scope_info_;
2334 2335 2336 2337
  }

  // Allocate ScopeInfos for inner scopes.
  for (Scope* scope = inner_scope_; scope != nullptr; scope = scope->sibling_) {
2338 2339 2340 2341 2342 2343 2344 2345 2346 2347 2348 2349 2350 2351 2352 2353
    if (!scope->is_function_scope() ||
        scope->AsDeclarationScope()->ShouldEagerCompile()) {
      scope->AllocateScopeInfosRecursively(isolate, next_outer_scope);
    }
  }
}

void Scope::AllocateDebuggerScopeInfos(Isolate* isolate,
                                       MaybeHandle<ScopeInfo> outer_scope) {
  if (scope_info_.is_null()) {
    scope_info_ = ScopeInfo::Create(isolate, zone(), this, outer_scope);
  }
  MaybeHandle<ScopeInfo> outer = NeedsContext() ? scope_info_ : outer_scope;
  for (Scope* scope = inner_scope_; scope != nullptr; scope = scope->sibling_) {
    if (scope->is_function_scope()) continue;
    scope->AllocateDebuggerScopeInfos(isolate, outer);
2354 2355
  }
}
2356

2357 2358 2359 2360 2361 2362 2363 2364 2365 2366 2367 2368 2369 2370 2371 2372 2373 2374 2375 2376 2377 2378 2379 2380 2381 2382 2383 2384 2385 2386 2387 2388
// static
void DeclarationScope::AllocateScopeInfos(ParseInfo* info, Isolate* isolate,
                                          AnalyzeMode mode) {
  DeclarationScope* scope = info->literal()->scope();
  if (!scope->scope_info_.is_null()) return;  // Allocated by outer function.

  MaybeHandle<ScopeInfo> outer_scope;
  if (scope->outer_scope_ != nullptr) {
    outer_scope = scope->outer_scope_->scope_info_;
  }

  scope->AllocateScopeInfosRecursively(isolate, outer_scope);
  if (mode == AnalyzeMode::kDebugger) {
    scope->AllocateDebuggerScopeInfos(isolate, outer_scope);
  }

  // The debugger expects all shared function infos to contain a scope info.
  // Since the top-most scope will end up in a shared function info, make sure
  // it has one, even if it doesn't need a scope info.
  // TODO(jochen|yangguo): Remove this requirement.
  if (scope->scope_info_.is_null()) {
    scope->scope_info_ =
        ScopeInfo::Create(isolate, scope->zone(), scope, outer_scope);
  }

  // Ensuring that the outer script scope has a scope info avoids having
  // special case for native contexts vs other contexts.
  if (info->script_scope() && info->script_scope()->scope_info_.is_null()) {
    info->script_scope()->scope_info_ = handle(ScopeInfo::Empty(isolate));
  }
}

2389
int Scope::StackLocalCount() const {
2390 2391
  Variable* function =
      is_function_scope() ? AsDeclarationScope()->function_var() : nullptr;
2392
  return num_stack_slots() -
2393
         (function != nullptr && function->IsStackLocal() ? 1 : 0);
2394
}
2395 2396


2397 2398
int Scope::ContextLocalCount() const {
  if (num_heap_slots() == 0) return 0;
2399 2400
  Variable* function =
      is_function_scope() ? AsDeclarationScope()->function_var() : nullptr;
2401
  bool is_function_var_in_context =
2402
      function != nullptr && function->IsContextSlot();
2403
  return num_heap_slots() - Context::MIN_CONTEXT_SLOTS -
2404
         (is_function_var_in_context ? 1 : 0);
2405
}
2406

2407 2408
}  // namespace internal
}  // namespace v8