scope-info.cc 34.6 KB
Newer Older
1
// Copyright 2011 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 <stdlib.h>
6

7 8
#include "src/objects/scope-info.h"

9
#include "src/ast/scopes.h"
10
#include "src/ast/variables.h"
11
#include "src/bootstrapper.h"
12

marja's avatar
marja committed
13
#include "src/objects-inl.h"
14
#include "src/objects/module-inl.h"
15

16 17
namespace v8 {
namespace internal {
18

19 20 21 22 23 24 25
// An entry in ModuleVariableEntries consists of several slots:
enum ModuleVariableEntryOffset {
  kModuleVariableNameOffset,
  kModuleVariableIndexOffset,
  kModuleVariablePropertiesOffset,
  kModuleVariableEntryLength  // Sentinel value.
};
26

jochen's avatar
jochen committed
27
#ifdef DEBUG
28
bool ScopeInfo::Equals(ScopeInfo other) const {
jochen's avatar
jochen committed
29 30
  if (length() != other->length()) return false;
  for (int index = 0; index < length(); ++index) {
31 32
    Object entry = get(index);
    Object other_entry = other->get(index);
jochen's avatar
jochen committed
33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60
    if (entry->IsSmi()) {
      if (entry != other_entry) return false;
    } else {
      if (HeapObject::cast(entry)->map()->instance_type() !=
          HeapObject::cast(other_entry)->map()->instance_type()) {
        return false;
      }
      if (entry->IsString()) {
        if (!String::cast(entry)->Equals(String::cast(other_entry))) {
          return false;
        }
      } else if (entry->IsScopeInfo()) {
        if (!ScopeInfo::cast(entry)->Equals(ScopeInfo::cast(other_entry))) {
          return false;
        }
      } else if (entry->IsModuleInfo()) {
        if (!ModuleInfo::cast(entry)->Equals(ModuleInfo::cast(other_entry))) {
          return false;
        }
      } else {
        UNREACHABLE();
      }
    }
  }
  return true;
}
#endif

61
// static
jochen's avatar
jochen committed
62 63
Handle<ScopeInfo> ScopeInfo::Create(Isolate* isolate, Zone* zone, Scope* scope,
                                    MaybeHandle<ScopeInfo> outer_scope) {
64
  // Collect variables.
65
  int context_local_count = 0;
66
  int module_vars_count = 0;
67 68 69 70
  // Stack allocated block scope variables are allocated in the parent
  // declaration scope, but are recorded in the block scope's scope info. First
  // slot index indicates at which offset a particular scope starts in the
  // parent declaration scope.
71
  for (Variable* var : *scope->locals()) {
72 73 74 75 76 77 78 79 80
    switch (var->location()) {
      case VariableLocation::CONTEXT:
        context_local_count++;
        break;
      case VariableLocation::MODULE:
        module_vars_count++;
        break;
      default:
        break;
81 82
    }
  }
83 84
  // Determine use and location of the "this" binding if it is present.
  VariableAllocationInfo receiver_info;
85 86 87
  if (scope->is_declaration_scope() &&
      scope->AsDeclarationScope()->has_this_declaration()) {
    Variable* var = scope->AsDeclarationScope()->receiver();
88 89 90 91
    if (!var->is_used()) {
      receiver_info = UNUSED;
    } else if (var->IsContextSlot()) {
      receiver_info = CONTEXT;
92
      context_local_count++;
93 94 95 96 97 98 99 100
    } else {
      DCHECK(var->IsParameter());
      receiver_info = STACK;
    }
  } else {
    receiver_info = NONE;
  }

101 102 103 104 105
  DCHECK(module_vars_count == 0 || scope->is_module_scope());

  // Make sure we allocate the correct amount.
  DCHECK_EQ(scope->ContextLocalCount(), context_local_count);

106
  const bool has_new_target =
107 108
      scope->is_declaration_scope() &&
      scope->AsDeclarationScope()->new_target_var() != nullptr;
109 110
  // TODO(cbruni): Don't always waste a field for the inferred name.
  const bool has_inferred_function_name = scope->is_function_scope();
111

112
  // Determine use and location of the function variable if it is present.
113
  VariableAllocationInfo function_name_info;
114 115 116 117 118 119 120 121 122 123 124
  if (scope->is_function_scope()) {
    if (scope->AsDeclarationScope()->function_var() != nullptr) {
      Variable* var = scope->AsDeclarationScope()->function_var();
      if (!var->is_used()) {
        function_name_info = UNUSED;
      } else if (var->IsContextSlot()) {
        function_name_info = CONTEXT;
      } else {
        DCHECK(var->IsStackLocal());
        function_name_info = STACK;
      }
125
    } else {
126 127
      // Always reserve space for the debug name in the scope info.
      function_name_info = UNUSED;
128
    }
129 130 131 132
  } else if (scope->is_module_scope() || scope->is_script_scope() ||
             scope->is_eval_scope()) {
    // Always reserve space for the debug name in the scope info.
    function_name_info = UNUSED;
133
  } else {
134
    function_name_info = NONE;
135 136
  }

137
  const bool has_function_name = function_name_info != NONE;
138
  const bool has_position_info = NeedsPositionInfo(scope->scope_type());
139
  const bool has_receiver = receiver_info == STACK || receiver_info == CONTEXT;
140 141 142 143
  const int parameter_count =
      scope->is_declaration_scope()
          ? scope->AsDeclarationScope()->num_parameters()
          : 0;
jochen's avatar
jochen committed
144
  const bool has_outer_scope_info = !outer_scope.is_null();
145 146
  const int length = kVariablePartIndex + 2 * context_local_count +
                     (has_receiver ? 1 : 0) +
147
                     (has_function_name ? kFunctionNameEntries : 0) +
148
                     (has_inferred_function_name ? 1 : 0) +
149
                     (has_position_info ? kPositionInfoEntries : 0) +
jochen's avatar
jochen committed
150
                     (has_outer_scope_info ? 1 : 0) +
151 152 153
                     (scope->is_module_scope()
                          ? 2 + kModuleVariableEntryLength * module_vars_count
                          : 0);
154

155 156 157 158 159 160 161
  Handle<ScopeInfo> scope_info_handle =
      isolate->factory()->NewScopeInfo(length);
  int index = kVariablePartIndex;
  {
    DisallowHeapAllocation no_gc;
    ScopeInfo scope_info = *scope_info_handle;
    WriteBarrierMode mode = scope_info->GetWriteBarrierMode(no_gc);
162

163 164 165 166 167 168 169 170 171 172 173 174 175
    bool has_simple_parameters = false;
    bool is_asm_module = false;
    bool calls_sloppy_eval = false;
    if (scope->is_function_scope()) {
      DeclarationScope* function_scope = scope->AsDeclarationScope();
      has_simple_parameters = function_scope->has_simple_parameters();
      is_asm_module = function_scope->is_asm_module();
    }
    FunctionKind function_kind = kNormalFunction;
    if (scope->is_declaration_scope()) {
      function_kind = scope->AsDeclarationScope()->function_kind();
      calls_sloppy_eval = scope->AsDeclarationScope()->calls_sloppy_eval();
    }
176

177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194
    // Encode the flags.
    int flags =
        ScopeTypeField::encode(scope->scope_type()) |
        CallsSloppyEvalField::encode(calls_sloppy_eval) |
        LanguageModeField::encode(scope->language_mode()) |
        DeclarationScopeField::encode(scope->is_declaration_scope()) |
        ReceiverVariableField::encode(receiver_info) |
        HasNewTargetField::encode(has_new_target) |
        FunctionVariableField::encode(function_name_info) |
        HasInferredFunctionNameField::encode(has_inferred_function_name) |
        IsAsmModuleField::encode(is_asm_module) |
        HasSimpleParametersField::encode(has_simple_parameters) |
        FunctionKindField::encode(function_kind) |
        HasOuterScopeInfoField::encode(has_outer_scope_info) |
        IsDebugEvaluateScopeField::encode(scope->is_debug_evaluate_scope()) |
        ForceContextAllocationField::encode(
            scope->ForceContextForLanguageMode());
    scope_info->SetFlags(flags);
195

196 197
    scope_info->SetParameterCount(parameter_count);
    scope_info->SetContextLocalCount(context_local_count);
198

199 200 201 202 203
    // Add context locals' names and info, module variables' names and info.
    // Context locals are added using their index.
    int context_local_base = index;
    int context_local_info_base = context_local_base + context_local_count;
    int module_var_entry = scope_info->ModuleVariablesIndex();
204

205 206 207 208 209 210 211 212 213 214 215 216 217 218 219
    for (Variable* var : *scope->locals()) {
      switch (var->location()) {
        case VariableLocation::CONTEXT: {
          // Due to duplicate parameters, context locals aren't guaranteed to
          // come in order.
          int local_index = var->index() - Context::MIN_CONTEXT_SLOTS;
          DCHECK_LE(0, local_index);
          DCHECK_LT(local_index, context_local_count);
          uint32_t info =
              VariableModeField::encode(var->mode()) |
              InitFlagField::encode(var->initialization_flag()) |
              MaybeAssignedFlagField::encode(var->maybe_assigned()) |
              ParameterNumberField::encode(ParameterNumberField::kMax);
          scope_info->set(context_local_base + local_index, *var->name(), mode);
          scope_info->set(context_local_info_base + local_index,
220
                          Smi::FromInt(info));
221 222 223 224 225 226
          break;
        }
        case VariableLocation::MODULE: {
          scope_info->set(module_var_entry + kModuleVariableNameOffset,
                          *var->name(), mode);
          scope_info->set(module_var_entry + kModuleVariableIndexOffset,
227
                          Smi::FromInt(var->index()));
228 229 230 231 232 233
          uint32_t properties =
              VariableModeField::encode(var->mode()) |
              InitFlagField::encode(var->initialization_flag()) |
              MaybeAssignedFlagField::encode(var->maybe_assigned()) |
              ParameterNumberField::encode(ParameterNumberField::kMax);
          scope_info->set(module_var_entry + kModuleVariablePropertiesOffset,
234
                          Smi::FromInt(properties));
235 236 237 238 239
          module_var_entry += kModuleVariableEntryLength;
          break;
        }
        default:
          break;
240
      }
241
    }
242

243 244 245 246 247 248 249 250 251 252 253 254 255 256 257
    if (scope->is_declaration_scope()) {
      // Mark contexts slots with the parameter number they represent. We walk
      // the list of parameters. That can include duplicate entries if a
      // parameter name is repeated. By walking upwards, we'll automatically
      // mark the context slot with the highest parameter number that uses this
      // variable. That will be the parameter number that is represented by the
      // context slot. All lower parameters will only be available on the stack
      // through the arguments object.
      for (int i = 0; i < parameter_count; i++) {
        Variable* parameter = scope->AsDeclarationScope()->parameter(i);
        if (parameter->location() != VariableLocation::CONTEXT) continue;
        int index = parameter->index() - Context::MIN_CONTEXT_SLOTS;
        int info_index = context_local_info_base + index;
        int info = Smi::ToInt(scope_info->get(info_index));
        info = ParameterNumberField::update(info, i);
258
        scope_info->set(info_index, Smi::FromInt(info));
259
      }
260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275

      // TODO(verwaest): Remove this unnecessary entry.
      if (scope->AsDeclarationScope()->has_this_declaration()) {
        Variable* var = scope->AsDeclarationScope()->receiver();
        if (var->location() == VariableLocation::CONTEXT) {
          int local_index = var->index() - Context::MIN_CONTEXT_SLOTS;
          uint32_t info =
              VariableModeField::encode(var->mode()) |
              InitFlagField::encode(var->initialization_flag()) |
              MaybeAssignedFlagField::encode(var->maybe_assigned()) |
              ParameterNumberField::encode(ParameterNumberField::kMax);
          scope_info->set(context_local_base + local_index, *var->name(), mode);
          scope_info->set(context_local_info_base + local_index,
                          Smi::FromInt(info));
        }
      }
276 277
    }

278
    index += 2 * context_local_count;
279

280 281 282 283
    // If the receiver is allocated, add its index.
    DCHECK_EQ(index, scope_info->ReceiverInfoIndex());
    if (has_receiver) {
      int var_index = scope->AsDeclarationScope()->receiver()->index();
284
      scope_info->set(index++, Smi::FromInt(var_index));
285 286 287
      // ?? DCHECK(receiver_info != CONTEXT || var_index ==
      // scope_info->ContextLength() - 1);
    }
288

289 290 291 292 293 294 295 296 297 298 299
    // If present, add the function variable name and its index.
    DCHECK_EQ(index, scope_info->FunctionNameInfoIndex());
    if (has_function_name) {
      Variable* var = scope->AsDeclarationScope()->function_var();
      int var_index = -1;
      Object name = Smi::kZero;
      if (var != nullptr) {
        var_index = var->index();
        name = *var->name();
      }
      scope_info->set(index++, name, mode);
300
      scope_info->set(index++, Smi::FromInt(var_index));
301 302
      DCHECK(function_name_info != CONTEXT ||
             var_index == scope_info->ContextLength() - 1);
303
    }
304

305 306 307 308 309
    DCHECK_EQ(index, scope_info->InferredFunctionNameIndex());
    if (has_inferred_function_name) {
      // The inferred function name is taken from the SFI.
      index++;
    }
310

311 312
    DCHECK_EQ(index, scope_info->PositionInfoIndex());
    if (has_position_info) {
313 314
      scope_info->set(index++, Smi::FromInt(scope->start_position()));
      scope_info->set(index++, Smi::FromInt(scope->end_position()));
315
    }
316

317 318 319 320 321
    // If present, add the outer scope info.
    DCHECK(index == scope_info->OuterScopeInfoIndex());
    if (has_outer_scope_info) {
      scope_info->set(index++, *outer_scope.ToHandleChecked(), mode);
    }
jochen's avatar
jochen committed
322 323
  }

324 325 326
  // Module-specific information (only for module scopes).
  if (scope->is_module_scope()) {
    Handle<ModuleInfo> module_info =
327
        ModuleInfo::New(isolate, zone, scope->AsModuleScope()->module());
328 329 330 331 332
    DCHECK_EQ(index, scope_info_handle->ModuleInfoIndex());
    scope_info_handle->set(index++, *module_info);
    DCHECK_EQ(index, scope_info_handle->ModuleVariableCountIndex());
    scope_info_handle->set(index++, Smi::FromInt(module_vars_count));
    DCHECK_EQ(index, scope_info_handle->ModuleVariablesIndex());
333 334 335 336
    // The variable entries themselves have already been written above.
    index += kModuleVariableEntryLength * module_vars_count;
  }

337
  DCHECK_EQ(index, scope_info_handle->length());
338
  DCHECK_EQ(parameter_count, scope_info_handle->ParameterCount());
339 340
  DCHECK_EQ(scope->num_heap_slots(), scope_info_handle->ContextLength());
  return scope_info_handle;
341 342
}

343
// static
jochen's avatar
jochen committed
344 345 346
Handle<ScopeInfo> ScopeInfo::CreateForWithScope(
    Isolate* isolate, MaybeHandle<ScopeInfo> outer_scope) {
  const bool has_outer_scope_info = !outer_scope.is_null();
347
  const int length = kVariablePartIndex + (has_outer_scope_info ? 1 : 0);
348 349 350 351 352 353

  Factory* factory = isolate->factory();
  Handle<ScopeInfo> scope_info = factory->NewScopeInfo(length);

  // Encode the flags.
  int flags =
354
      ScopeTypeField::encode(WITH_SCOPE) | CallsSloppyEvalField::encode(false) |
355 356
      LanguageModeField::encode(LanguageMode::kSloppy) |
      DeclarationScopeField::encode(false) |
357
      ReceiverVariableField::encode(NONE) | HasNewTargetField::encode(false) |
358
      FunctionVariableField::encode(NONE) | IsAsmModuleField::encode(false) |
359
      HasSimpleParametersField::encode(true) |
jochen's avatar
jochen committed
360
      FunctionKindField::encode(kNormalFunction) |
361 362
      HasOuterScopeInfoField::encode(has_outer_scope_info) |
      IsDebugEvaluateScopeField::encode(false);
363 364 365 366 367 368
  scope_info->SetFlags(flags);

  scope_info->SetParameterCount(0);
  scope_info->SetContextLocalCount(0);

  int index = kVariablePartIndex;
369 370
  DCHECK_EQ(index, scope_info->ReceiverInfoIndex());
  DCHECK_EQ(index, scope_info->FunctionNameInfoIndex());
371
  DCHECK_EQ(index, scope_info->InferredFunctionNameIndex());
372
  DCHECK_EQ(index, scope_info->PositionInfoIndex());
373
  DCHECK(index == scope_info->OuterScopeInfoIndex());
jochen's avatar
jochen committed
374 375 376
  if (has_outer_scope_info) {
    scope_info->set(index++, *outer_scope.ToHandleChecked());
  }
377 378 379 380 381
  DCHECK_EQ(index, scope_info->length());
  DCHECK_EQ(0, scope_info->ParameterCount());
  DCHECK_EQ(Context::MIN_CONTEXT_SLOTS, scope_info->ContextLength());
  return scope_info;
}
382

383
// static
384
Handle<ScopeInfo> ScopeInfo::CreateGlobalThisBinding(Isolate* isolate) {
385 386 387 388 389 390 391 392 393 394 395 396
  return CreateForBootstrapping(isolate, SCRIPT_SCOPE);
}

// static
Handle<ScopeInfo> ScopeInfo::CreateForEmptyFunction(Isolate* isolate) {
  return CreateForBootstrapping(isolate, FUNCTION_SCOPE);
}

// static
Handle<ScopeInfo> ScopeInfo::CreateForBootstrapping(Isolate* isolate,
                                                    ScopeType type) {
  DCHECK(type == SCRIPT_SCOPE || type == FUNCTION_SCOPE);
397

398 399 400 401 402
  const int parameter_count = 0;
  const bool is_empty_function = type == FUNCTION_SCOPE;
  const int context_local_count = is_empty_function ? 0 : 1;
  const bool has_receiver = !is_empty_function;
  const bool has_inferred_function_name = is_empty_function;
403
  const bool has_position_info = true;
404 405
  const int length = kVariablePartIndex + 2 * context_local_count +
                     (has_receiver ? 1 : 0) +
406 407
                     (is_empty_function ? kFunctionNameEntries : 0) +
                     (has_inferred_function_name ? 1 : 0) +
408
                     (has_position_info ? kPositionInfoEntries : 0);
409 410 411 412 413

  Factory* factory = isolate->factory();
  Handle<ScopeInfo> scope_info = factory->NewScopeInfo(length);

  // Encode the flags.
414 415 416 417 418 419 420 421
  int flags =
      ScopeTypeField::encode(type) | CallsSloppyEvalField::encode(false) |
      LanguageModeField::encode(LanguageMode::kSloppy) |
      DeclarationScopeField::encode(true) |
      ReceiverVariableField::encode(is_empty_function ? UNUSED : CONTEXT) |
      HasNewTargetField::encode(false) |
      FunctionVariableField::encode(is_empty_function ? UNUSED : NONE) |
      HasInferredFunctionNameField::encode(has_inferred_function_name) |
422
      IsAsmModuleField::encode(false) | HasSimpleParametersField::encode(true) |
423 424 425
      FunctionKindField::encode(FunctionKind::kNormalFunction) |
      HasOuterScopeInfoField::encode(false) |
      IsDebugEvaluateScopeField::encode(false);
426 427 428 429 430 431 432
  scope_info->SetFlags(flags);
  scope_info->SetParameterCount(parameter_count);
  scope_info->SetContextLocalCount(context_local_count);

  int index = kVariablePartIndex;

  // Here we add info for context-allocated "this".
433
  DCHECK_EQ(index, scope_info->ContextLocalNamesIndex());
434
  if (context_local_count) {
435
    scope_info->set(index++, ReadOnlyRoots(isolate).this_string());
436
  }
437
  DCHECK_EQ(index, scope_info->ContextLocalInfosIndex());
438
  if (context_local_count) {
439 440 441 442 443
    const uint32_t value =
        VariableModeField::encode(VariableMode::kConst) |
        InitFlagField::encode(kCreatedInitialized) |
        MaybeAssignedFlagField::encode(kNotAssigned) |
        ParameterNumberField::encode(ParameterNumberField::kMax);
444 445
    scope_info->set(index++, Smi::FromInt(value));
  }
446 447

  // And here we record that this scopeinfo binds a receiver.
448
  DCHECK_EQ(index, scope_info->ReceiverInfoIndex());
449
  const int receiver_index = Context::MIN_CONTEXT_SLOTS + 0;
450 451 452
  if (!is_empty_function) {
    scope_info->set(index++, Smi::FromInt(receiver_index));
  }
453

454
  DCHECK_EQ(index, scope_info->FunctionNameInfoIndex());
455 456 457 458
  if (is_empty_function) {
    scope_info->set(index++, *isolate->factory()->empty_string());
    scope_info->set(index++, Smi::kZero);
  }
459
  DCHECK_EQ(index, scope_info->InferredFunctionNameIndex());
460 461 462
  if (has_inferred_function_name) {
    scope_info->set(index++, *isolate->factory()->empty_string());
  }
463 464 465 466
  DCHECK_EQ(index, scope_info->PositionInfoIndex());
  // Store dummy position to be in sync with the {scope_type}.
  scope_info->set(index++, Smi::kZero);
  scope_info->set(index++, Smi::kZero);
467
  DCHECK_EQ(index, scope_info->OuterScopeInfoIndex());
468
  DCHECK_EQ(index, scope_info->length());
469 470 471 472 473 474
  DCHECK_EQ(scope_info->ParameterCount(), parameter_count);
  if (type == FUNCTION_SCOPE) {
    DCHECK_EQ(scope_info->ContextLength(), 0);
  } else {
    DCHECK_EQ(scope_info->ContextLength(), Context::MIN_CONTEXT_SLOTS + 1);
  }
475 476 477 478

  return scope_info;
}

479
ScopeInfo ScopeInfo::Empty(Isolate* isolate) {
480
  return ReadOnlyRoots(isolate).empty_scope_info();
481 482
}

483
ScopeType ScopeInfo::scope_type() const {
484
  DCHECK_LT(0, length());
485
  return ScopeTypeField::decode(Flags());
486 487
}

488
bool ScopeInfo::CallsSloppyEval() const {
489 490 491 492 493
  bool calls_sloppy_eval =
      length() > 0 && CallsSloppyEvalField::decode(Flags());
  DCHECK_IMPLIES(calls_sloppy_eval, is_sloppy(language_mode()));
  DCHECK_IMPLIES(calls_sloppy_eval, is_declaration_scope());
  return calls_sloppy_eval;
494 495
}

496
LanguageMode ScopeInfo::language_mode() const {
497 498
  return length() > 0 ? LanguageModeField::decode(Flags())
                      : LanguageMode::kSloppy;
499 500
}

501
bool ScopeInfo::is_declaration_scope() const {
502 503 504
  return DeclarationScopeField::decode(Flags());
}

505
int ScopeInfo::ContextLength() const {
506 507 508 509
  if (length() > 0) {
    int context_locals = ContextLocalCount();
    bool function_name_context_slot =
        FunctionVariableField::decode(Flags()) == CONTEXT;
510 511 512
    bool force_context = ForceContextAllocationField::decode(Flags());
    bool has_context = context_locals > 0 || force_context ||
                       function_name_context_slot ||
513
                       scope_type() == WITH_SCOPE ||
514
                       (scope_type() == BLOCK_SCOPE && CallsSloppyEval() &&
515
                        is_declaration_scope()) ||
516
                       (scope_type() == FUNCTION_SCOPE && CallsSloppyEval()) ||
517
                       (scope_type() == FUNCTION_SCOPE && IsAsmModule()) ||
518
                       scope_type() == MODULE_SCOPE;
519

520
    if (has_context) {
521
      return Context::MIN_CONTEXT_SLOTS + context_locals +
522
             (function_name_context_slot ? 1 : 0);
523
    }
524
  }
525
  return 0;
526 527
}

528
bool ScopeInfo::HasReceiver() const {
529 530
  if (length() == 0) return false;
  return NONE != ReceiverVariableField::decode(Flags());
531 532
}

533
bool ScopeInfo::HasAllocatedReceiver() const {
534 535 536
  if (length() == 0) return false;
  VariableAllocationInfo allocation = ReceiverVariableField::decode(Flags());
  return allocation == STACK || allocation == CONTEXT;
537 538
}

539 540 541
bool ScopeInfo::HasNewTarget() const {
  return HasNewTargetField::decode(Flags());
}
542

543
bool ScopeInfo::HasFunctionName() const {
544 545 546 547
  if (length() == 0) return false;
  return NONE != FunctionVariableField::decode(Flags());
}

548 549 550 551 552
bool ScopeInfo::HasInferredFunctionName() const {
  if (length() == 0) return false;
  return HasInferredFunctionNameField::decode(Flags());
}

553 554 555 556 557 558 559 560 561
bool ScopeInfo::HasPositionInfo() const {
  if (length() == 0) return false;
  return NeedsPositionInfo(scope_type());
}

// static
bool ScopeInfo::NeedsPositionInfo(ScopeType type) {
  return type == FUNCTION_SCOPE || type == SCRIPT_SCOPE || type == EVAL_SCOPE ||
         type == MODULE_SCOPE;
562 563
}

564 565
bool ScopeInfo::HasSharedFunctionName() const {
  return FunctionName() != SharedFunctionInfo::kNoSharedNameSentinel;
566 567
}

568
void ScopeInfo::SetFunctionName(Object name) {
569 570
  DCHECK(HasFunctionName());
  DCHECK(name->IsString() || name == SharedFunctionInfo::kNoSharedNameSentinel);
571 572 573
  set(FunctionNameInfoIndex(), name);
}

574
void ScopeInfo::SetInferredFunctionName(String name) {
575 576 577 578
  DCHECK(HasInferredFunctionName());
  set(InferredFunctionNameIndex(), name);
}

579
bool ScopeInfo::HasOuterScopeInfo() const {
580 581
  if (length() == 0) return false;
  return HasOuterScopeInfoField::decode(Flags());
jochen's avatar
jochen committed
582
}
583

584
bool ScopeInfo::IsDebugEvaluateScope() const {
585 586
  if (length() == 0) return false;
  return IsDebugEvaluateScopeField::decode(Flags());
587 588 589 590 591 592 593 594 595 596 597
}

void ScopeInfo::SetIsDebugEvaluateScope() {
  if (length() > 0) {
    DCHECK_EQ(scope_type(), WITH_SCOPE);
    SetFlags(Flags() | IsDebugEvaluateScopeField::encode(true));
  } else {
    UNREACHABLE();
  }
}

598
bool ScopeInfo::HasContext() const { return ContextLength() > 0; }
599

600
Object ScopeInfo::FunctionName() const {
601
  DCHECK(HasFunctionName());
602
  return get(FunctionNameInfoIndex());
603 604
}

605
Object ScopeInfo::InferredFunctionName() const {
606 607 608 609
  DCHECK(HasInferredFunctionName());
  return get(InferredFunctionNameIndex());
}

610
String ScopeInfo::FunctionDebugName() const {
611
  Object name = FunctionName();
612 613 614 615 616 617 618
  if (name->IsString() && String::cast(name)->length() > 0) {
    return String::cast(name);
  }
  if (HasInferredFunctionName()) {
    name = InferredFunctionName();
    if (name->IsString()) return String::cast(name);
  }
619
  return GetReadOnlyRoots().empty_string();
620 621
}

622
int ScopeInfo::StartPosition() const {
623
  DCHECK(HasPositionInfo());
624
  return Smi::ToInt(get(PositionInfoIndex()));
625 626
}

627
int ScopeInfo::EndPosition() const {
628
  DCHECK(HasPositionInfo());
629
  return Smi::ToInt(get(PositionInfoIndex() + 1));
630 631 632 633 634 635 636 637 638
}

void ScopeInfo::SetPositionInfo(int start, int end) {
  DCHECK(HasPositionInfo());
  DCHECK_LE(start, end);
  set(PositionInfoIndex(), Smi::FromInt(start));
  set(PositionInfoIndex() + 1, Smi::FromInt(end));
}

639
ScopeInfo ScopeInfo::OuterScopeInfo() const {
jochen's avatar
jochen committed
640
  DCHECK(HasOuterScopeInfo());
641
  return ScopeInfo::cast(get(OuterScopeInfoIndex()));
jochen's avatar
jochen committed
642 643
}

644
ModuleInfo ScopeInfo::ModuleDescriptorInfo() const {
645
  DCHECK(scope_type() == MODULE_SCOPE);
646
  return ModuleInfo::cast(get(ModuleInfoIndex()));
647
}
648

649
String ScopeInfo::ContextLocalName(int var) const {
650 651
  DCHECK_LE(0, var);
  DCHECK_LT(var, ContextLocalCount());
652
  int info_index = ContextLocalNamesIndex() + var;
653
  return String::cast(get(info_index));
654 655
}

656
VariableMode ScopeInfo::ContextLocalMode(int var) const {
657 658
  DCHECK_LE(0, var);
  DCHECK_LT(var, ContextLocalCount());
659
  int info_index = ContextLocalInfosIndex() + var;
jgruber's avatar
jgruber committed
660
  int value = Smi::ToInt(get(info_index));
661
  return VariableModeField::decode(value);
662 663
}

664
InitializationFlag ScopeInfo::ContextLocalInitFlag(int var) const {
665 666
  DCHECK_LE(0, var);
  DCHECK_LT(var, ContextLocalCount());
667
  int info_index = ContextLocalInfosIndex() + var;
jgruber's avatar
jgruber committed
668
  int value = Smi::ToInt(get(info_index));
669
  return InitFlagField::decode(value);
670 671
}

672 673 674 675 676 677 678 679 680 681 682 683 684 685 686
bool ScopeInfo::ContextLocalIsParameter(int var) const {
  DCHECK_LE(0, var);
  DCHECK_LT(var, ContextLocalCount());
  int info_index = ContextLocalInfosIndex() + var;
  int value = Smi::ToInt(get(info_index));
  return ParameterNumberField::decode(value) != ParameterNumberField::kMax;
}

uint32_t ScopeInfo::ContextLocalParameterNumber(int var) const {
  DCHECK(ContextLocalIsParameter(var));
  int info_index = ContextLocalInfosIndex() + var;
  int value = Smi::ToInt(get(info_index));
  return ParameterNumberField::decode(value);
}

687
MaybeAssignedFlag ScopeInfo::ContextLocalMaybeAssignedFlag(int var) const {
688 689
  DCHECK_LE(0, var);
  DCHECK_LT(var, ContextLocalCount());
690
  int info_index = ContextLocalInfosIndex() + var;
jgruber's avatar
jgruber committed
691
  int value = Smi::ToInt(get(info_index));
692
  return MaybeAssignedFlagField::decode(value);
693 694
}

695
// static
696
bool ScopeInfo::VariableIsSynthetic(String name) {
697 698 699 700
  // There's currently no flag stored on the ScopeInfo to indicate that a
  // variable is a compiler-introduced temporary. However, to avoid conflict
  // with user declarations, the current temporaries like .generator_object and
  // .result start with a dot, so we can use that as a flag. It's a hack!
701
  return name->length() == 0 || name->Get(0) == '.' ||
702
         name->Equals(name->GetReadOnlyRoots().this_string());
703 704
}

705
int ScopeInfo::ModuleIndex(String name, VariableMode* mode,
706 707
                           InitializationFlag* init_flag,
                           MaybeAssignedFlag* maybe_assigned_flag) {
708
  DisallowHeapAllocation no_gc;
709
  DCHECK(name->IsInternalizedString());
710 711 712 713 714
  DCHECK_EQ(scope_type(), MODULE_SCOPE);
  DCHECK_NOT_NULL(mode);
  DCHECK_NOT_NULL(init_flag);
  DCHECK_NOT_NULL(maybe_assigned_flag);

jgruber's avatar
jgruber committed
715
  int module_vars_count = Smi::ToInt(get(ModuleVariableCountIndex()));
716
  int entry = ModuleVariablesIndex();
717
  for (int i = 0; i < module_vars_count; ++i) {
718
    String var_name = String::cast(get(entry + kModuleVariableNameOffset));
719
    if (name->Equals(var_name)) {
720 721
      int index;
      ModuleVariable(i, nullptr, &index, mode, init_flag, maybe_assigned_flag);
722 723 724 725 726
      return index;
    }
    entry += kModuleVariableEntryLength;
  }

727
  return 0;
728
}
729

730
// static
731 732
int ScopeInfo::ContextSlotIndex(ScopeInfo scope_info, String name,
                                VariableMode* mode,
733 734
                                InitializationFlag* init_flag,
                                MaybeAssignedFlag* maybe_assigned_flag) {
735
  DisallowHeapAllocation no_gc;
736
  DCHECK(name->IsInternalizedString());
737 738 739 740
  DCHECK_NOT_NULL(mode);
  DCHECK_NOT_NULL(init_flag);
  DCHECK_NOT_NULL(maybe_assigned_flag);

741 742 743 744 745
  if (scope_info->length() == 0) return -1;

  int start = scope_info->ContextLocalNamesIndex();
  int end = start + scope_info->ContextLocalCount();
  for (int i = start; i < end; ++i) {
746 747 748 749 750 751 752 753 754
    if (name != scope_info->get(i)) continue;
    int var = i - start;
    *mode = scope_info->ContextLocalMode(var);
    *init_flag = scope_info->ContextLocalInitFlag(var);
    *maybe_assigned_flag = scope_info->ContextLocalMaybeAssignedFlag(var);
    int result = Context::MIN_CONTEXT_SLOTS + var;

    DCHECK_LT(result, scope_info->ContextLength());
    return result;
755
  }
756

757 758 759
  return -1;
}

760 761
int ScopeInfo::ReceiverContextSlotIndex() const {
  if (length() > 0 && ReceiverVariableField::decode(Flags()) == CONTEXT) {
jgruber's avatar
jgruber committed
762
    return Smi::ToInt(get(ReceiverInfoIndex()));
763
  }
764 765 766
  return -1;
}

767
int ScopeInfo::FunctionContextSlotIndex(String name) const {
768
  DCHECK(name->IsInternalizedString());
769
  if (length() > 0) {
770 771
    if (FunctionVariableField::decode(Flags()) == CONTEXT &&
        FunctionName() == name) {
jgruber's avatar
jgruber committed
772
      return Smi::ToInt(get(FunctionNameInfoIndex() + 1));
773 774 775 776 777
    }
  }
  return -1;
}

778
FunctionKind ScopeInfo::function_kind() const {
779 780 781
  return FunctionKindField::decode(Flags());
}

782
int ScopeInfo::ContextLocalNamesIndex() const {
783
  DCHECK_LT(0, length());
784 785 786
  return kVariablePartIndex;
}

787
int ScopeInfo::ContextLocalInfosIndex() const {
788
  return ContextLocalNamesIndex() + ContextLocalCount();
789 790
}

791
int ScopeInfo::ReceiverInfoIndex() const {
792
  return ContextLocalInfosIndex() + ContextLocalCount();
793 794
}

795
int ScopeInfo::FunctionNameInfoIndex() const {
796
  return ReceiverInfoIndex() + (HasAllocatedReceiver() ? 1 : 0);
797 798
}

799
int ScopeInfo::InferredFunctionNameIndex() const {
800 801 802 803
  return FunctionNameInfoIndex() +
         (HasFunctionName() ? kFunctionNameEntries : 0);
}

804 805 806 807
int ScopeInfo::PositionInfoIndex() const {
  return InferredFunctionNameIndex() + (HasInferredFunctionName() ? 1 : 0);
}

808
int ScopeInfo::OuterScopeInfoIndex() const {
809
  return PositionInfoIndex() + (HasPositionInfo() ? kPositionInfoEntries : 0);
810 811
}

812
int ScopeInfo::ModuleInfoIndex() const {
813
  return OuterScopeInfoIndex() + (HasOuterScopeInfo() ? 1 : 0);
jochen's avatar
jochen committed
814 815
}

816 817 818
int ScopeInfo::ModuleVariableCountIndex() const {
  return ModuleInfoIndex() + 1;
}
819

820 821 822
int ScopeInfo::ModuleVariablesIndex() const {
  return ModuleVariableCountIndex() + 1;
}
823

824
void ScopeInfo::ModuleVariable(int i, String* name, int* index,
825 826 827 828
                               VariableMode* mode,
                               InitializationFlag* init_flag,
                               MaybeAssignedFlag* maybe_assigned_flag) {
  DCHECK_LE(0, i);
jgruber's avatar
jgruber committed
829
  DCHECK_LT(i, Smi::ToInt(get(ModuleVariableCountIndex())));
830 831

  int entry = ModuleVariablesIndex() + i * kModuleVariableEntryLength;
jgruber's avatar
jgruber committed
832
  int properties = Smi::ToInt(get(entry + kModuleVariablePropertiesOffset));
833 834 835 836 837

  if (name != nullptr) {
    *name = String::cast(get(entry + kModuleVariableNameOffset));
  }
  if (index != nullptr) {
jgruber's avatar
jgruber committed
838
    *index = Smi::ToInt(get(entry + kModuleVariableIndexOffset));
839
    DCHECK_NE(*index, 0);
840 841 842 843 844 845 846 847 848 849 850 851
  }
  if (mode != nullptr) {
    *mode = VariableModeField::decode(properties);
  }
  if (init_flag != nullptr) {
    *init_flag = InitFlagField::decode(properties);
  }
  if (maybe_assigned_flag != nullptr) {
    *maybe_assigned_flag = MaybeAssignedFlagField::decode(properties);
  }
}

852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867
std::ostream& operator<<(std::ostream& os,
                         ScopeInfo::VariableAllocationInfo var_info) {
  switch (var_info) {
    case ScopeInfo::VariableAllocationInfo::NONE:
      return os << "NONE";
    case ScopeInfo::VariableAllocationInfo::STACK:
      return os << "STACK";
    case ScopeInfo::VariableAllocationInfo::CONTEXT:
      return os << "CONTEXT";
    case ScopeInfo::VariableAllocationInfo::UNUSED:
      return os << "UNUSED";
  }
  UNREACHABLE();
  return os;
}

868 869 870 871
Handle<ModuleInfoEntry> ModuleInfoEntry::New(Isolate* isolate,
                                             Handle<Object> export_name,
                                             Handle<Object> local_name,
                                             Handle<Object> import_name,
872
                                             int module_request, int cell_index,
873
                                             int beg_pos, int end_pos) {
874 875 876
  Handle<ModuleInfoEntry> result =
      Handle<ModuleInfoEntry>::cast(isolate->factory()->NewStruct(
          MODULE_INFO_ENTRY_TYPE, AllocationType::kOld));
877 878 879 880 881 882 883
  result->set_export_name(*export_name);
  result->set_local_name(*local_name);
  result->set_import_name(*import_name);
  result->set_module_request(module_request);
  result->set_cell_index(cell_index);
  result->set_beg_pos(beg_pos);
  result->set_end_pos(end_pos);
884 885 886
  return result;
}

887 888
Handle<ModuleInfo> ModuleInfo::New(Isolate* isolate, Zone* zone,
                                   ModuleDescriptor* descr) {
889
  // Serialize module requests.
890 891 892 893
  int size = static_cast<int>(descr->module_requests().size());
  Handle<FixedArray> module_requests = isolate->factory()->NewFixedArray(size);
  Handle<FixedArray> module_request_positions =
      isolate->factory()->NewFixedArray(size);
894
  for (const auto& elem : descr->module_requests()) {
895 896 897
    module_requests->set(elem.second.index, *elem.first->string());
    module_request_positions->set(elem.second.index,
                                  Smi::FromInt(elem.second.position));
898 899
  }

900
  // Serialize special exports.
901 902
  Handle<FixedArray> special_exports = isolate->factory()->NewFixedArray(
      static_cast<int>(descr->special_exports().size()));
903 904 905
  {
    int i = 0;
    for (auto entry : descr->special_exports()) {
906 907
      Handle<ModuleInfoEntry> serialized_entry = entry->Serialize(isolate);
      special_exports->set(i++, *serialized_entry);
908 909 910
    }
  }

911
  // Serialize namespace imports.
912 913
  Handle<FixedArray> namespace_imports = isolate->factory()->NewFixedArray(
      static_cast<int>(descr->namespace_imports().size()));
914 915
  {
    int i = 0;
916
    for (auto entry : descr->namespace_imports()) {
917 918
      Handle<ModuleInfoEntry> serialized_entry = entry->Serialize(isolate);
      namespace_imports->set(i++, *serialized_entry);
919 920 921
    }
  }

922
  // Serialize regular exports.
923 924
  Handle<FixedArray> regular_exports =
      descr->SerializeRegularExports(isolate, zone);
925

926 927 928 929 930 931
  // Serialize regular imports.
  Handle<FixedArray> regular_imports = isolate->factory()->NewFixedArray(
      static_cast<int>(descr->regular_imports().size()));
  {
    int i = 0;
    for (const auto& elem : descr->regular_imports()) {
932 933 934
      Handle<ModuleInfoEntry> serialized_entry =
          elem.second->Serialize(isolate);
      regular_imports->set(i++, *serialized_entry);
935 936 937
    }
  }

938
  Handle<ModuleInfo> result = isolate->factory()->NewModuleInfo();
939
  result->set(kModuleRequestsIndex, *module_requests);
940 941
  result->set(kSpecialExportsIndex, *special_exports);
  result->set(kRegularExportsIndex, *regular_exports);
942
  result->set(kNamespaceImportsIndex, *namespace_imports);
943
  result->set(kRegularImportsIndex, *regular_imports);
944
  result->set(kModuleRequestPositionsIndex, *module_request_positions);
945 946
  return result;
}
947

948 949 950 951 952
int ModuleInfo::RegularExportCount() const {
  DCHECK_EQ(regular_exports()->length() % kRegularExportLength, 0);
  return regular_exports()->length() / kRegularExportLength;
}

953
String ModuleInfo::RegularExportLocalName(int i) const {
954 955 956 957 958
  return String::cast(regular_exports()->get(i * kRegularExportLength +
                                             kRegularExportLocalNameOffset));
}

int ModuleInfo::RegularExportCellIndex(int i) const {
959 960
  return Smi::ToInt(regular_exports()->get(i * kRegularExportLength +
                                           kRegularExportCellIndexOffset));
961 962
}

963
FixedArray ModuleInfo::RegularExportExportNames(int i) const {
964 965 966 967
  return FixedArray::cast(regular_exports()->get(
      i * kRegularExportLength + kRegularExportExportNamesOffset));
}

968 969
}  // namespace internal
}  // namespace v8