// 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/objects-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

Handle<ScopeInfo> ScopeInfo::Create(Isolate* isolate, Zone* zone, Scope* scope,
                                    MaybeHandle<ScopeInfo> outer_scope) {
  // Collect variables.
  int stack_local_count = 0;
  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.
  int first_slot_index = 0;
  for (Variable* var : *scope->locals()) {
    switch (var->location()) {
      case VariableLocation::LOCAL:
        if (stack_local_count == 0) first_slot_index = var->index();
        stack_local_count++;
        break;
      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;
  }

  bool has_new_target =
      scope->is_declaration_scope() &&
      scope->AsDeclarationScope()->new_target_var() != nullptr;

  // Determine use and location of the function variable if it is present.
  VariableAllocationInfo function_name_info;
  if (scope->is_function_scope() &&
      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 {
    function_name_info = NONE;
  }

  const bool has_function_name = function_name_info != NONE;
  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 + parameter_count +
                     (1 + stack_local_count) + 2 * context_local_count +
                     (has_receiver ? 1 : 0) + (has_function_name ? 2 : 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) |
      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->SetStackLocalCount(stack_local_count);
  scope_info->SetContextLocalCount(context_local_count);

  int index = kVariablePartIndex;
  // Add parameters.
  DCHECK_EQ(index, scope_info->ParameterNamesIndex());
  if (scope->is_declaration_scope()) {
    for (int i = 0; i < parameter_count; ++i) {
      scope_info->set(index++,
                      *scope->AsDeclarationScope()->parameter(i)->name());
    }
  }

  // Add stack locals' names, context locals' names and info, module variables'
  // names and info. We are assuming that the stack locals' slots are allocated
  // in increasing order, so we can simply add them to the ScopeInfo object.
  // Context locals are added using their index.
  DCHECK_EQ(index, scope_info->StackLocalFirstSlotIndex());
  scope_info->set(index++, Smi::FromInt(first_slot_index));
  DCHECK_EQ(index, scope_info->StackLocalNamesIndex());

  int stack_local_base = index;
  int context_local_base = stack_local_base + stack_local_count;
  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::LOCAL: {
        int local_index = var->index() - first_slot_index;
        DCHECK_LE(0, local_index);
        DCHECK_LT(local_index, stack_local_count);
        scope_info->set(stack_local_base + local_index, *var->name());
        break;
      }
      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());
        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());
        scope_info->set(module_var_entry + kModuleVariablePropertiesOffset,
                        Smi::FromInt(properties));
        module_var_entry += kModuleVariableEntryLength;
        break;
      }
      default:
        break;
    }
  }

  index += stack_local_count + 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) {
    int var_index = scope->AsDeclarationScope()->function_var()->index();
    scope_info->set(index++,
                    *scope->AsDeclarationScope()->function_var()->name());
    scope_info->set(index++, Smi::FromInt(var_index));
    DCHECK(function_name_info != CONTEXT ||
           var_index == scope_info->ContextLength() - 1);
  }

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

Handle<ScopeInfo> ScopeInfo::CreateForWithScope(
    Isolate* isolate, MaybeHandle<ScopeInfo> outer_scope) {
  const bool has_outer_scope_info = !outer_scope.is_null();
  const int length = kVariablePartIndex + 1 + (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(SLOPPY) | 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->SetStackLocalCount(0);
  scope_info->SetContextLocalCount(0);

  int index = kVariablePartIndex;
  DCHECK_EQ(index, scope_info->ParameterNamesIndex());
  DCHECK_EQ(index, scope_info->StackLocalFirstSlotIndex());
  scope_info->set(index++, Smi::kZero);
  DCHECK_EQ(index, scope_info->StackLocalNamesIndex());
  DCHECK_EQ(index, scope_info->ReceiverInfoIndex());
  DCHECK_EQ(index, scope_info->FunctionNameInfoIndex());
  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;
}

Handle<ScopeInfo> ScopeInfo::CreateGlobalThisBinding(Isolate* isolate) {
  DCHECK(isolate->bootstrapper()->IsActive());

  const int stack_local_count = 0;
  const int context_local_count = 1;
  const bool has_simple_parameters = true;
  const VariableAllocationInfo receiver_info = CONTEXT;
  const VariableAllocationInfo function_name_info = NONE;
  const bool has_function_name = false;
  const bool has_receiver = true;
  const bool has_outer_scope_info = false;
  const int parameter_count = 0;
  const int length = kVariablePartIndex + parameter_count +
                     (1 + stack_local_count) + 2 * context_local_count +
                     (has_receiver ? 1 : 0) + (has_function_name ? 2 : 0) +
                     (has_outer_scope_info ? 1 : 0);

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

  // Encode the flags.
  int flags = ScopeTypeField::encode(SCRIPT_SCOPE) |
              CallsSloppyEvalField::encode(false) |
              LanguageModeField::encode(SLOPPY) |
              DeclarationScopeField::encode(true) |
              ReceiverVariableField::encode(receiver_info) |
              FunctionVariableField::encode(function_name_info) |
              AsmModuleField::encode(false) |
              HasSimpleParametersField::encode(has_simple_parameters) |
              FunctionKindField::encode(FunctionKind::kNormalFunction) |
              HasOuterScopeInfoField::encode(has_outer_scope_info) |
              IsDebugEvaluateScopeField::encode(false);
  scope_info->SetFlags(flags);
  scope_info->SetParameterCount(parameter_count);
  scope_info->SetStackLocalCount(stack_local_count);
  scope_info->SetContextLocalCount(context_local_count);

  int index = kVariablePartIndex;
  const int first_slot_index = 0;
  DCHECK_EQ(index, scope_info->StackLocalFirstSlotIndex());
  scope_info->set(index++, Smi::FromInt(first_slot_index));
  DCHECK_EQ(index, scope_info->StackLocalNamesIndex());

  // Here we add info for context-allocated "this".
  DCHECK_EQ(index, scope_info->ContextLocalNamesIndex());
  scope_info->set(index++, isolate->heap()->this_string());
  DCHECK_EQ(index, scope_info->ContextLocalInfosIndex());
  const uint32_t value = VariableModeField::encode(CONST) |
                         InitFlagField::encode(kCreatedInitialized) |
                         MaybeAssignedFlagField::encode(kNotAssigned);
  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;
  scope_info->set(index++, Smi::FromInt(receiver_index));

  DCHECK_EQ(index, scope_info->FunctionNameInfoIndex());
  DCHECK_EQ(index, scope_info->OuterScopeInfoIndex());
  DCHECK_EQ(index, scope_info->length());
  DCHECK_EQ(scope_info->ParameterCount(), 0);
  DCHECK_EQ(scope_info->ContextLength(), Context::MIN_CONTEXT_SLOTS + 1);

  return scope_info;
}

ScopeInfo* ScopeInfo::Empty(Isolate* isolate) {
  return isolate->heap()->empty_scope_info();
}

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

bool ScopeInfo::CallsSloppyEval() {
  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() {
  return length() > 0 ? LanguageModeField::decode(Flags()) : SLOPPY;
}

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

int ScopeInfo::LocalCount() { return StackLocalCount() + ContextLocalCount(); }

int ScopeInfo::StackSlotCount() {
  if (length() > 0) {
    bool function_name_stack_slot =
        FunctionVariableField::decode(Flags()) == STACK;
    return StackLocalCount() + (function_name_stack_slot ? 1 : 0);
  }
  return 0;
}

int ScopeInfo::ContextLength() {
  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() {
  if (length() > 0) {
    return NONE != ReceiverVariableField::decode(Flags());
  } else {
    return false;
  }
}

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

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

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

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

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

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

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

String* ScopeInfo::FunctionName() {
  DCHECK(HasFunctionName());
  return String::cast(get(FunctionNameInfoIndex()));
}

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

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

String* ScopeInfo::ParameterName(int var) {
  DCHECK_LE(0, var);
  DCHECK_LT(var, ParameterCount());
  int info_index = ParameterNamesIndex() + var;
  return String::cast(get(info_index));
}

String* ScopeInfo::LocalName(int var) {
  DCHECK_LE(0, var);
  DCHECK_LT(var, LocalCount());
  DCHECK(StackLocalNamesIndex() + StackLocalCount() ==
         ContextLocalNamesIndex());
  int info_index = StackLocalNamesIndex() + var;
  return String::cast(get(info_index));
}

String* ScopeInfo::StackLocalName(int var) {
  DCHECK_LE(0, var);
  DCHECK_LT(var, StackLocalCount());
  int info_index = StackLocalNamesIndex() + var;
  return String::cast(get(info_index));
}

int ScopeInfo::StackLocalIndex(int var) {
  DCHECK_LE(0, var);
  DCHECK_LT(var, StackLocalCount());
  int first_slot_index = Smi::ToInt(get(StackLocalFirstSlotIndex()));
  return first_slot_index + var;
}

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

VariableMode ScopeInfo::ContextLocalMode(int var) {
  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) {
  DCHECK_LE(0, var);
  DCHECK_LT(var, ContextLocalCount());
  int info_index = ContextLocalInfosIndex() + var;
  int value = Smi::ToInt(get(info_index));
  return InitFlagField::decode(value);
}

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

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->GetHeap()->this_string());
}

int ScopeInfo::StackSlotIndex(String* name) {
  DCHECK(name->IsInternalizedString());
  if (length() > 0) {
    int first_slot_index = Smi::ToInt(get(StackLocalFirstSlotIndex()));
    int start = StackLocalNamesIndex();
    int end = start + StackLocalCount();
    for (int i = start; i < end; ++i) {
      if (name == get(i)) {
        return i - start + first_slot_index;
      }
    }
  }
  return -1;
}

int ScopeInfo::ModuleIndex(Handle<String> name, VariableMode* mode,
                           InitializationFlag* init_flag,
                           MaybeAssignedFlag* maybe_assigned_flag) {
  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;
}

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) {
    ContextSlotCache* context_slot_cache =
        scope_info->GetIsolate()->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, TEMPORARY,
                               kNeedsInitialization, kNotAssigned, -1);
  }

  return -1;
}

int ScopeInfo::ParameterIndex(String* name) {
  DCHECK(name->IsInternalizedString());
  if (length() > 0) {
    // We must read parameters from the end since for
    // multiply declared parameters the value of the
    // last declaration of that parameter is used
    // inside a function (and thus we need to look
    // at the last index). Was bug# 1110337.
    int start = ParameterNamesIndex();
    int end = start + ParameterCount();
    for (int i = end - 1; i >= start; --i) {
      if (name == get(i)) {
        return i - start;
      }
    }
  }
  return -1;
}

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

int ScopeInfo::FunctionContextSlotIndex(String* name) {
  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() {
  return FunctionKindField::decode(Flags());
}

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

int ScopeInfo::StackLocalFirstSlotIndex() {
  return ParameterNamesIndex() + ParameterCount();
}

int ScopeInfo::StackLocalNamesIndex() { return StackLocalFirstSlotIndex() + 1; }

int ScopeInfo::ContextLocalNamesIndex() {
  return StackLocalNamesIndex() + StackLocalCount();
}

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

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

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

int ScopeInfo::OuterScopeInfoIndex() {
  return FunctionNameInfoIndex() + (HasFunctionName() ? 2 : 0);
}

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

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

int ScopeInfo::ModuleVariablesIndex() { 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);
  }
}

#ifdef DEBUG

static void PrintList(const char* list_name, int nof_internal_slots, int start,
                      int end, ScopeInfo* scope_info) {
  if (start < end) {
    PrintF("\n  // %s\n", list_name);
    if (nof_internal_slots > 0) {
      PrintF("  %2d - %2d [internal slots]\n", 0, nof_internal_slots - 1);
    }
    for (int i = nof_internal_slots; start < end; ++i, ++start) {
      PrintF("  %2d ", i);
      String::cast(scope_info->get(start))->ShortPrint();
      PrintF("\n");
    }
  }
}

void ScopeInfo::Print() {
  PrintF("ScopeInfo ");
  if (HasFunctionName()) {
    FunctionName()->ShortPrint();
  } else {
    PrintF("/* no function name */");
  }
  PrintF("{");

  if (length() > 0) {
    PrintList("parameters", 0, ParameterNamesIndex(),
              ParameterNamesIndex() + ParameterCount(), this);
    PrintList("stack slots", 0, StackLocalNamesIndex(),
              StackLocalNamesIndex() + StackLocalCount(), this);
    PrintList("context slots", Context::MIN_CONTEXT_SLOTS,
              ContextLocalNamesIndex(),
              ContextLocalNamesIndex() + ContextLocalCount(), this);
    // TODO(neis): Print module stuff if present.
  }

  PrintF("}\n");
}
#endif  // DEBUG

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(descr->special_exports().length());
  {
    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(descr->namespace_imports().length());
  {
    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::cast(regular_exports()->get(i * kRegularExportLength +
                                          kRegularExportCellIndexOffset))
      ->value();
}

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

}  // namespace internal
}  // namespace v8
