// Copyright 2011 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include <stdlib.h>

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

#include "src/ast/context-slot-cache.h"
#include "src/ast/scopes.h"
#include "src/ast/variables.h"
#include "src/bootstrapper.h"
#include "src/heap/heap-inl.h"
#include "src/objects-inl.h"
#include "src/objects/module-inl.h"

namespace v8 {
namespace internal {

// An entry in ModuleVariableEntries consists of several slots:
enum ModuleVariableEntryOffset {
  kModuleVariableNameOffset,
  kModuleVariableIndexOffset,
  kModuleVariablePropertiesOffset,
  kModuleVariableEntryLength  // Sentinel value.
};

#ifdef DEBUG
bool ScopeInfo::Equals(ScopeInfo* other) const {
  if (length() != other->length()) return false;
  for (int index = 0; index < length(); ++index) {
    Object* entry = get(index);
    Object* other_entry = other->get(index);
    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

// static
Handle<ScopeInfo> ScopeInfo::Create(Isolate* isolate, Zone* zone, Scope* scope,
                                    MaybeHandle<ScopeInfo> outer_scope) {
  // Collect variables.
  int context_local_count = 0;
  int module_vars_count = 0;
  // 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.
  for (Variable* var : *scope->locals()) {
    switch (var->location()) {
      case VariableLocation::CONTEXT:
        context_local_count++;
        break;
      case VariableLocation::MODULE:
        module_vars_count++;
        break;
      default:
        break;
    }
  }
  DCHECK(module_vars_count == 0 || scope->is_module_scope());

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

  // Determine use and location of the "this" binding if it is present.
  VariableAllocationInfo receiver_info;
  if (scope->is_declaration_scope() &&
      scope->AsDeclarationScope()->has_this_declaration()) {
    Variable* var = scope->AsDeclarationScope()->receiver();
    if (!var->is_used()) {
      receiver_info = UNUSED;
    } else if (var->IsContextSlot()) {
      receiver_info = CONTEXT;
    } else {
      DCHECK(var->IsParameter());
      receiver_info = STACK;
    }
  } else {
    receiver_info = NONE;
  }

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

  // Determine use and location of the function variable if it is present.
  VariableAllocationInfo function_name_info;
  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;
      }
    } else {
      // Always reserve space for the debug name in the scope info.
      function_name_info = UNUSED;
    }
  } 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;
  } else {
    function_name_info = NONE;
  }

  const bool has_function_name = function_name_info != NONE;
  const bool has_position_info = NeedsPositionInfo(scope->scope_type());
  const bool has_receiver = receiver_info == STACK || receiver_info == CONTEXT;
  const int parameter_count = scope->num_parameters();
  const bool has_outer_scope_info = !outer_scope.is_null();
  const int length = kVariablePartIndex + 2 * context_local_count +
                     (has_receiver ? 1 : 0) +
                     (has_function_name ? kFunctionNameEntries : 0) +
                     (has_inferred_function_name ? 1 : 0) +
                     (has_position_info ? kPositionInfoEntries : 0) +
                     (has_outer_scope_info ? 1 : 0) +
                     (scope->is_module_scope()
                          ? 2 + kModuleVariableEntryLength * module_vars_count
                          : 0);

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

  bool has_simple_parameters = false;
  bool 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();
    asm_module = function_scope->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();
  }

  // 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) |
      AsmModuleField::encode(asm_module) |
      HasSimpleParametersField::encode(has_simple_parameters) |
      FunctionKindField::encode(function_kind) |
      HasOuterScopeInfoField::encode(has_outer_scope_info) |
      IsDebugEvaluateScopeField::encode(scope->is_debug_evaluate_scope());
  scope_info->SetFlags(flags);

  scope_info->SetParameterCount(parameter_count);
  scope_info->SetContextLocalCount(context_local_count);

  int index = kVariablePartIndex;

  // 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();

  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());
        scope_info->set(context_local_info_base + local_index,
                        Smi::FromInt(info));
        break;
      }
      case VariableLocation::MODULE: {
        scope_info->set(module_var_entry + kModuleVariableNameOffset,
                        *var->name());
        scope_info->set(module_var_entry + kModuleVariableIndexOffset,
                        Smi::FromInt(var->index()));
        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,
                        Smi::FromInt(properties));
        module_var_entry += kModuleVariableEntryLength;
        break;
      }
      default:
        break;
    }
  }

  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);
      scope_info->set(info_index, Smi::FromInt(info));
    }
  }

  index += 2 * context_local_count;

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

  // If present, add the function variable name and its index.
  DCHECK_EQ(index, scope_info->FunctionNameInfoIndex());
  if (has_function_name) {
    DisallowHeapAllocation no_gc;
    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);
    scope_info->set(index++, Smi::FromInt(var_index));
    DCHECK(function_name_info != CONTEXT ||
           var_index == scope_info->ContextLength() - 1);
  }

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

  DCHECK_EQ(index, scope_info->PositionInfoIndex());
  if (has_position_info) {
    scope_info->set(index++, Smi::FromInt(scope->start_position()));
    scope_info->set(index++, Smi::FromInt(scope->end_position()));
  }

  // If present, add the outer scope info.
  DCHECK(index == scope_info->OuterScopeInfoIndex());
  if (has_outer_scope_info) {
    scope_info->set(index++, *outer_scope.ToHandleChecked());
  }

  // Module-specific information (only for module scopes).
  if (scope->is_module_scope()) {
    Handle<ModuleInfo> module_info =
        ModuleInfo::New(isolate, zone, scope->AsModuleScope()->module());
    DCHECK_EQ(index, scope_info->ModuleInfoIndex());
    scope_info->set(index++, *module_info);
    DCHECK_EQ(index, scope_info->ModuleVariableCountIndex());
    scope_info->set(index++, Smi::FromInt(module_vars_count));
    DCHECK_EQ(index, scope_info->ModuleVariablesIndex());
    // The variable entries themselves have already been written above.
    index += kModuleVariableEntryLength * module_vars_count;
  }

  DCHECK_EQ(index, scope_info->length());
  DCHECK_EQ(scope->num_parameters(), scope_info->ParameterCount());
  DCHECK_EQ(scope->num_heap_slots(), scope_info->ContextLength());
  return scope_info;
}

// static
Handle<ScopeInfo> ScopeInfo::CreateForWithScope(
    Isolate* isolate, MaybeHandle<ScopeInfo> outer_scope) {
  const bool has_outer_scope_info = !outer_scope.is_null();
  const int length = kVariablePartIndex + (has_outer_scope_info ? 1 : 0);

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

  // Encode the flags.
  int flags =
      ScopeTypeField::encode(WITH_SCOPE) | CallsSloppyEvalField::encode(false) |
      LanguageModeField::encode(LanguageMode::kSloppy) |
      DeclarationScopeField::encode(false) |
      ReceiverVariableField::encode(NONE) | HasNewTargetField::encode(false) |
      FunctionVariableField::encode(NONE) | AsmModuleField::encode(false) |
      HasSimpleParametersField::encode(true) |
      FunctionKindField::encode(kNormalFunction) |
      HasOuterScopeInfoField::encode(has_outer_scope_info) |
      IsDebugEvaluateScopeField::encode(false);
  scope_info->SetFlags(flags);

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

  int index = kVariablePartIndex;
  DCHECK_EQ(index, scope_info->ReceiverInfoIndex());
  DCHECK_EQ(index, scope_info->FunctionNameInfoIndex());
  DCHECK_EQ(index, scope_info->InferredFunctionNameIndex());
  DCHECK_EQ(index, scope_info->PositionInfoIndex());
  DCHECK(index == scope_info->OuterScopeInfoIndex());
  if (has_outer_scope_info) {
    scope_info->set(index++, *outer_scope.ToHandleChecked());
  }
  DCHECK_EQ(index, scope_info->length());
  DCHECK_EQ(0, scope_info->ParameterCount());
  DCHECK_EQ(Context::MIN_CONTEXT_SLOTS, scope_info->ContextLength());
  return scope_info;
}

// static
Handle<ScopeInfo> ScopeInfo::CreateGlobalThisBinding(Isolate* isolate) {
  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(isolate->bootstrapper()->IsActive());
  DCHECK(type == SCRIPT_SCOPE || type == FUNCTION_SCOPE);

  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;
  const bool has_position_info = true;
  const int length = kVariablePartIndex + 2 * context_local_count +
                     (has_receiver ? 1 : 0) +
                     (is_empty_function ? kFunctionNameEntries : 0) +
                     (has_inferred_function_name ? 1 : 0) +
                     (has_position_info ? kPositionInfoEntries : 0);

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

  // Encode the flags.
  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) |
      AsmModuleField::encode(false) | HasSimpleParametersField::encode(true) |
      FunctionKindField::encode(FunctionKind::kNormalFunction) |
      HasOuterScopeInfoField::encode(false) |
      IsDebugEvaluateScopeField::encode(false);
  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".
  DCHECK_EQ(index, scope_info->ContextLocalNamesIndex());
  if (context_local_count) {
    scope_info->set(index++, ReadOnlyRoots(isolate).this_string());
  }
  DCHECK_EQ(index, scope_info->ContextLocalInfosIndex());
  if (context_local_count) {
    const uint32_t value =
        VariableModeField::encode(VariableMode::kConst) |
        InitFlagField::encode(kCreatedInitialized) |
        MaybeAssignedFlagField::encode(kNotAssigned) |
        ParameterNumberField::encode(ParameterNumberField::kMax);
    scope_info->set(index++, Smi::FromInt(value));
  }

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

  DCHECK_EQ(index, scope_info->FunctionNameInfoIndex());
  if (is_empty_function) {
    scope_info->set(index++, *isolate->factory()->empty_string());
    scope_info->set(index++, Smi::kZero);
  }
  DCHECK_EQ(index, scope_info->InferredFunctionNameIndex());
  if (has_inferred_function_name) {
    scope_info->set(index++, *isolate->factory()->empty_string());
  }
  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);
  DCHECK_EQ(index, scope_info->OuterScopeInfoIndex());
  DCHECK_EQ(index, scope_info->length());
  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);
  }

  return scope_info;
}

ScopeInfo* ScopeInfo::Empty(Isolate* isolate) {
  return ReadOnlyRoots(isolate).empty_scope_info();
}

ScopeType ScopeInfo::scope_type() const {
  DCHECK_LT(0, length());
  return ScopeTypeField::decode(Flags());
}

bool ScopeInfo::CallsSloppyEval() const {
  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;
}

LanguageMode ScopeInfo::language_mode() const {
  return length() > 0 ? LanguageModeField::decode(Flags())
                      : LanguageMode::kSloppy;
}

bool ScopeInfo::is_declaration_scope() const {
  return DeclarationScopeField::decode(Flags());
}

int ScopeInfo::ContextLength() const {
  if (length() > 0) {
    int context_locals = ContextLocalCount();
    bool function_name_context_slot =
        FunctionVariableField::decode(Flags()) == CONTEXT;
    bool has_context = context_locals > 0 || function_name_context_slot ||
                       scope_type() == WITH_SCOPE ||
                       (scope_type() == BLOCK_SCOPE && CallsSloppyEval() &&
                        is_declaration_scope()) ||
                       (scope_type() == FUNCTION_SCOPE && CallsSloppyEval()) ||
                       (scope_type() == FUNCTION_SCOPE && IsAsmModule()) ||
                       scope_type() == MODULE_SCOPE;

    if (has_context) {
      return Context::MIN_CONTEXT_SLOTS + context_locals +
             (function_name_context_slot ? 1 : 0);
    }
  }
  return 0;
}

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

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

bool ScopeInfo::HasNewTarget() const {
  return HasNewTargetField::decode(Flags());
}

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

bool ScopeInfo::HasInferredFunctionName() const {
  if (length() == 0) return false;
  return HasInferredFunctionNameField::decode(Flags());
}

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;
}

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

void ScopeInfo::SetFunctionName(Object* name) {
  DCHECK(HasFunctionName());
  DCHECK(name->IsString() || name == SharedFunctionInfo::kNoSharedNameSentinel);
  set(FunctionNameInfoIndex(), name);
}

void ScopeInfo::SetInferredFunctionName(String* name) {
  DCHECK(HasInferredFunctionName());
  set(InferredFunctionNameIndex(), name);
}

bool ScopeInfo::HasOuterScopeInfo() const {
  if (length() == 0) return false;
  return HasOuterScopeInfoField::decode(Flags());
}

bool ScopeInfo::IsDebugEvaluateScope() const {
  if (length() == 0) return false;
  return IsDebugEvaluateScopeField::decode(Flags());
}

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

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

Object* ScopeInfo::FunctionName() const {
  DCHECK(HasFunctionName());
  return get(FunctionNameInfoIndex());
}

Object* ScopeInfo::InferredFunctionName() const {
  DCHECK(HasInferredFunctionName());
  return get(InferredFunctionNameIndex());
}

String* ScopeInfo::FunctionDebugName() const {
  Object* name = FunctionName();
  if (name->IsString() && String::cast(name)->length() > 0) {
    return String::cast(name);
  }
  if (HasInferredFunctionName()) {
    name = InferredFunctionName();
    if (name->IsString()) return String::cast(name);
  }
  return GetReadOnlyRoots().empty_string();
}

int ScopeInfo::StartPosition() const {
  DCHECK(HasPositionInfo());
  return Smi::ToInt(get(PositionInfoIndex()));
}

int ScopeInfo::EndPosition() const {
  DCHECK(HasPositionInfo());
  return Smi::ToInt(get(PositionInfoIndex() + 1));
}

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

ScopeInfo* ScopeInfo::OuterScopeInfo() const {
  DCHECK(HasOuterScopeInfo());
  return ScopeInfo::cast(get(OuterScopeInfoIndex()));
}

ModuleInfo* ScopeInfo::ModuleDescriptorInfo() const {
  DCHECK(scope_type() == MODULE_SCOPE);
  return ModuleInfo::cast(get(ModuleInfoIndex()));
}

String* ScopeInfo::ContextLocalName(int var) const {
  DCHECK_LE(0, var);
  DCHECK_LT(var, ContextLocalCount());
  int info_index = ContextLocalNamesIndex() + var;
  return String::cast(get(info_index));
}

VariableMode ScopeInfo::ContextLocalMode(int var) const {
  DCHECK_LE(0, var);
  DCHECK_LT(var, ContextLocalCount());
  int info_index = ContextLocalInfosIndex() + var;
  int value = Smi::ToInt(get(info_index));
  return VariableModeField::decode(value);
}

InitializationFlag ScopeInfo::ContextLocalInitFlag(int var) const {
  DCHECK_LE(0, var);
  DCHECK_LT(var, ContextLocalCount());
  int info_index = ContextLocalInfosIndex() + var;
  int value = Smi::ToInt(get(info_index));
  return InitFlagField::decode(value);
}

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);
}

MaybeAssignedFlag ScopeInfo::ContextLocalMaybeAssignedFlag(int var) const {
  DCHECK_LE(0, var);
  DCHECK_LT(var, ContextLocalCount());
  int info_index = ContextLocalInfosIndex() + var;
  int value = Smi::ToInt(get(info_index));
  return MaybeAssignedFlagField::decode(value);
}

// static
bool ScopeInfo::VariableIsSynthetic(String* name) {
  // 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!
  return name->length() == 0 || name->Get(0) == '.' ||
         name->Equals(name->GetReadOnlyRoots().this_string());
}

int ScopeInfo::ModuleIndex(Handle<String> name, VariableMode* mode,
                           InitializationFlag* init_flag,
                           MaybeAssignedFlag* maybe_assigned_flag) {
  DCHECK(name->IsInternalizedString());
  DCHECK_EQ(scope_type(), MODULE_SCOPE);
  DCHECK_NOT_NULL(mode);
  DCHECK_NOT_NULL(init_flag);
  DCHECK_NOT_NULL(maybe_assigned_flag);

  int module_vars_count = Smi::ToInt(get(ModuleVariableCountIndex()));
  int entry = ModuleVariablesIndex();
  for (int i = 0; i < module_vars_count; ++i) {
    String* var_name = String::cast(get(entry + kModuleVariableNameOffset));
    if (name->Equals(var_name)) {
      int index;
      ModuleVariable(i, nullptr, &index, mode, init_flag, maybe_assigned_flag);
      return index;
    }
    entry += kModuleVariableEntryLength;
  }

  return 0;
}

// static
int ScopeInfo::ContextSlotIndex(Handle<ScopeInfo> scope_info,
                                Handle<String> name, VariableMode* mode,
                                InitializationFlag* init_flag,
                                MaybeAssignedFlag* maybe_assigned_flag) {
  DCHECK(name->IsInternalizedString());
  DCHECK_NOT_NULL(mode);
  DCHECK_NOT_NULL(init_flag);
  DCHECK_NOT_NULL(maybe_assigned_flag);

  if (scope_info->length() == 0) return -1;

  // Get the Isolate via the heap.
  //
  // Ideally we'd pass Isolate* through to this function, however this is mostly
  // called from the parser, which is otherwise isolate independent. We can't
  // assume that all scope infos are never RO space (like we can with JSReceiver
  // or Context), but we can assume that *non-empty* scope infos are.
  //
  // So, we take the least-ugly approach of manually getting the isolate to be
  // able to remove GetIsolate from ScopeInfo in the general case, while
  // allowing it in this one particular case.
  Isolate* isolate = Heap::FromWritableHeapObject(*scope_info)->isolate();

  ContextSlotCache* context_slot_cache = isolate->context_slot_cache();
  int result = context_slot_cache->Lookup(*scope_info, *name, mode, init_flag,
                                          maybe_assigned_flag);
  if (result != ContextSlotCache::kNotFound) {
    DCHECK_LT(result, scope_info->ContextLength());
    return result;
  }

  int start = scope_info->ContextLocalNamesIndex();
  int end = start + scope_info->ContextLocalCount();
  for (int i = start; i < end; ++i) {
    if (*name == scope_info->get(i)) {
      int var = i - start;
      *mode = scope_info->ContextLocalMode(var);
      *init_flag = scope_info->ContextLocalInitFlag(var);
      *maybe_assigned_flag = scope_info->ContextLocalMaybeAssignedFlag(var);
      result = Context::MIN_CONTEXT_SLOTS + var;

      context_slot_cache->Update(scope_info, name, *mode, *init_flag,
                                 *maybe_assigned_flag, result);
      DCHECK_LT(result, scope_info->ContextLength());
      return result;
    }
  }
  // Cache as not found. Mode, init flag and maybe assigned flag don't matter.
  context_slot_cache->Update(scope_info, name, VariableMode::kTemporary,
                             kNeedsInitialization, kNotAssigned, -1);

  return -1;
}

int ScopeInfo::ReceiverContextSlotIndex() const {
  if (length() > 0 && ReceiverVariableField::decode(Flags()) == CONTEXT) {
    return Smi::ToInt(get(ReceiverInfoIndex()));
  }
  return -1;
}

int ScopeInfo::FunctionContextSlotIndex(String* name) const {
  DCHECK(name->IsInternalizedString());
  if (length() > 0) {
    if (FunctionVariableField::decode(Flags()) == CONTEXT &&
        FunctionName() == name) {
      return Smi::ToInt(get(FunctionNameInfoIndex() + 1));
    }
  }
  return -1;
}

FunctionKind ScopeInfo::function_kind() const {
  return FunctionKindField::decode(Flags());
}

int ScopeInfo::ContextLocalNamesIndex() const {
  DCHECK_LT(0, length());
  return kVariablePartIndex;
}

int ScopeInfo::ContextLocalInfosIndex() const {
  return ContextLocalNamesIndex() + ContextLocalCount();
}

int ScopeInfo::ReceiverInfoIndex() const {
  return ContextLocalInfosIndex() + ContextLocalCount();
}

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

int ScopeInfo::InferredFunctionNameIndex() const {
  return FunctionNameInfoIndex() +
         (HasFunctionName() ? kFunctionNameEntries : 0);
}

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

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

int ScopeInfo::ModuleInfoIndex() const {
  return OuterScopeInfoIndex() + (HasOuterScopeInfo() ? 1 : 0);
}

int ScopeInfo::ModuleVariableCountIndex() const {
  return ModuleInfoIndex() + 1;
}

int ScopeInfo::ModuleVariablesIndex() const {
  return ModuleVariableCountIndex() + 1;
}

void ScopeInfo::ModuleVariable(int i, String** name, int* index,
                               VariableMode* mode,
                               InitializationFlag* init_flag,
                               MaybeAssignedFlag* maybe_assigned_flag) {
  DCHECK_LE(0, i);
  DCHECK_LT(i, Smi::ToInt(get(ModuleVariableCountIndex())));

  int entry = ModuleVariablesIndex() + i * kModuleVariableEntryLength;
  int properties = Smi::ToInt(get(entry + kModuleVariablePropertiesOffset));

  if (name != nullptr) {
    *name = String::cast(get(entry + kModuleVariableNameOffset));
  }
  if (index != nullptr) {
    *index = Smi::ToInt(get(entry + kModuleVariableIndexOffset));
    DCHECK_NE(*index, 0);
  }
  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);
  }
}

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;
}

Handle<ModuleInfoEntry> ModuleInfoEntry::New(Isolate* isolate,
                                             Handle<Object> export_name,
                                             Handle<Object> local_name,
                                             Handle<Object> import_name,
                                             int module_request, int cell_index,
                                             int beg_pos, int end_pos) {
  Handle<ModuleInfoEntry> result = Handle<ModuleInfoEntry>::cast(
      isolate->factory()->NewStruct(MODULE_INFO_ENTRY_TYPE, TENURED));
  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);
  return result;
}

Handle<ModuleInfo> ModuleInfo::New(Isolate* isolate, Zone* zone,
                                   ModuleDescriptor* descr) {
  // Serialize module requests.
  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);
  for (const auto& elem : descr->module_requests()) {
    module_requests->set(elem.second.index, *elem.first->string());
    module_request_positions->set(elem.second.index,
                                  Smi::FromInt(elem.second.position));
  }

  // Serialize special exports.
  Handle<FixedArray> special_exports = isolate->factory()->NewFixedArray(
      static_cast<int>(descr->special_exports().size()));
  {
    int i = 0;
    for (auto entry : descr->special_exports()) {
      Handle<ModuleInfoEntry> serialized_entry = entry->Serialize(isolate);
      special_exports->set(i++, *serialized_entry);
    }
  }

  // Serialize namespace imports.
  Handle<FixedArray> namespace_imports = isolate->factory()->NewFixedArray(
      static_cast<int>(descr->namespace_imports().size()));
  {
    int i = 0;
    for (auto entry : descr->namespace_imports()) {
      Handle<ModuleInfoEntry> serialized_entry = entry->Serialize(isolate);
      namespace_imports->set(i++, *serialized_entry);
    }
  }

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

  // 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()) {
      Handle<ModuleInfoEntry> serialized_entry =
          elem.second->Serialize(isolate);
      regular_imports->set(i++, *serialized_entry);
    }
  }

  Handle<ModuleInfo> result = isolate->factory()->NewModuleInfo();
  result->set(kModuleRequestsIndex, *module_requests);
  result->set(kSpecialExportsIndex, *special_exports);
  result->set(kRegularExportsIndex, *regular_exports);
  result->set(kNamespaceImportsIndex, *namespace_imports);
  result->set(kRegularImportsIndex, *regular_imports);
  result->set(kModuleRequestPositionsIndex, *module_request_positions);
  return result;
}

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

String* ModuleInfo::RegularExportLocalName(int i) const {
  return String::cast(regular_exports()->get(i * kRegularExportLength +
                                             kRegularExportLocalNameOffset));
}

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

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

}  // namespace internal
}  // namespace v8
