// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
#if !defined(DART_PRECOMPILED_RUNTIME)

#include "vm/scopes.h"

#include "vm/compiler/backend/slot.h"
#include "vm/kernel.h"
#include "vm/object.h"
#include "vm/stack_frame.h"
#include "vm/symbols.h"

namespace dart {

DEFINE_FLAG(bool,
            share_enclosing_context,
            true,
            "Allocate captured variables in the existing context of an "
            "enclosing scope (up to innermost loop) and spare the allocation "
            "of a local context.");

LocalScope::LocalScope(LocalScope* parent, int function_level, int loop_level)
    : parent_(parent),
      child_(nullptr),
      sibling_(nullptr),
      function_level_(function_level),
      loop_level_(loop_level),
      context_level_(LocalScope::kUninitializedContextLevel),
      begin_token_pos_(TokenPosition::kNoSource),
      end_token_pos_(TokenPosition::kNoSource),
      variables_(),
      context_variables_(),
      context_slots_(new(Thread::Current()->zone())
                         ZoneGrowableArray<const Slot*>()) {
  // Hook this node into the children of the parent, unless the parent has a
  // different function_level, since the local scope of a nested function can
  // be discarded after it has been parsed.
  if ((parent != nullptr) && (parent->function_level() == function_level)) {
    sibling_ = parent->child_;
    parent->child_ = this;
  }
}

bool LocalScope::IsNestedWithin(LocalScope* scope) const {
  const LocalScope* current_scope = this;
  while (current_scope != nullptr) {
    if (current_scope == scope) {
      return true;
    }
    current_scope = current_scope->parent();
  }
  return false;
}

bool LocalScope::AddVariable(LocalVariable* variable) {
  ASSERT(variable != nullptr);
  if (LocalLookupVariable(variable->name(), variable->kernel_offset()) !=
      nullptr) {
    return false;
  }
  variables_.Add(variable);
  if (variable->owner() == nullptr) {
    // Variables must be added to their owner scope first. Subsequent calls
    // to 'add' treat the variable as an alias.
    variable->set_owner(this);
  }
  return true;
}

bool LocalScope::InsertParameterAt(intptr_t pos, LocalVariable* parameter) {
  ASSERT(parameter != nullptr);
  if (LocalLookupVariable(parameter->name(), parameter->kernel_offset()) !=
      nullptr) {
    return false;
  }
  variables_.InsertAt(pos, parameter);
  // InsertParameterAt is not used to add aliases of parameters.
  ASSERT(parameter->owner() == nullptr);
  parameter->set_owner(this);
  return true;
}

void LocalScope::AllocateContextVariable(LocalVariable* variable,
                                         LocalScope** context_owner) {
  ASSERT(variable->is_captured());
  ASSERT(variable->owner() == this);
  // The context level in the owner scope of a captured variable indicates at
  // code generation time how far to walk up the context chain in order to
  // access the variable from the current context level.
  if ((*context_owner) == nullptr) {
    ASSERT(num_context_variables() == 0);
    // This scope becomes the current context owner.
    set_context_level(1);
    *context_owner = this;
  } else if (!FLAG_share_enclosing_context && ((*context_owner) != this)) {
    // The captured variable is in a child scope of the context owner and we do
    // not share contexts.
    // This scope will allocate and chain a new context.
    ASSERT(num_context_variables() == 0);
    // This scope becomes the current context owner.
    set_context_level((*context_owner)->context_level() + 1);
    *context_owner = this;
  } else if ((*context_owner)->loop_level() < loop_level()) {
    ASSERT(FLAG_share_enclosing_context);
    // The captured variable is at a deeper loop level than the current context.
    // This scope will allocate and chain a new context.
    ASSERT(num_context_variables() == 0);
    // This scope becomes the current context owner.
    set_context_level((*context_owner)->context_level() + 1);
    *context_owner = this;
  } else {
    // Allocate the captured variable in the current context.
    if (!HasContextLevel()) {
      ASSERT(variable->owner() != *context_owner);
      set_context_level((*context_owner)->context_level());
    } else {
      ASSERT(context_level() == (*context_owner)->context_level());
    }
  }

  (*context_owner)->AddContextVariable(variable);
}

void LocalScope::AddContextVariable(LocalVariable* variable) {
  variable->set_index(VariableIndex(context_variables_.length()));
  context_variables_.Add(variable);
  context_slots_->Add(
      &Slot::GetContextVariableSlotFor(Thread::Current(), *variable));
}

VariableIndex LocalScope::AllocateVariables(const Function& function,
                                            VariableIndex first_parameter_index,
                                            int num_parameters,
                                            VariableIndex first_local_index,
                                            LocalScope* context_owner,
                                            bool* found_captured_variables) {
  // We should not allocate variables of nested functions while compiling an
  // enclosing function.
  ASSERT(function_level() == 0);
  ASSERT(num_parameters >= 0);
  // Parameters must be listed first and must all appear in the top scope.
  ASSERT(num_parameters <= num_variables());
  int pos = 0;  // Current variable position.
  VariableIndex next_index =
      first_parameter_index;  // Current free frame index.

  LocalVariable* suspend_state_var = nullptr;
  for (intptr_t i = 0; i < num_variables(); i++) {
    LocalVariable* variable = VariableAt(i);
    if (variable->owner() == this &&
        variable->name().Equals(Symbols::SuspendStateVar())) {
      ASSERT(!variable->is_captured());
      suspend_state_var = variable;
    }
  }

  if (suspend_state_var != nullptr) {
    suspend_state_var->set_index(
        VariableIndex(SuspendState::kSuspendStateVarIndex));
    ASSERT(next_index.value() == SuspendState::kSuspendStateVarIndex - 1);
  }

  while (pos < num_parameters) {
    LocalVariable* parameter = VariableAt(pos);
    pos++;
    // Parsing formal parameter default values may add local variable aliases
    // to the local scope before the formal parameters are added. However,
    // the parameters get inserted in front of the aliases, therefore, no
    // aliases can be encountered among the first num_parameters variables.
    ASSERT(parameter->owner() == this);
    if (parameter->is_captured()) {
      // A captured parameter has a slot allocated in the frame and one in the
      // context, where it gets copied to. The parameter index reflects the
      // context allocation index.
      next_index = VariableIndex(next_index.value() - 1);
      AllocateContextVariable(parameter, &context_owner);
      *found_captured_variables = true;
    } else {
      parameter->set_index(next_index);
      next_index = VariableIndex(next_index.value() - 1);
    }
  }
  // No overlapping of parameters and locals.
  ASSERT(next_index.value() >= first_local_index.value());
  next_index = first_local_index;
  for (; pos < num_variables(); pos++) {
    LocalVariable* variable = VariableAt(pos);
    if (variable == suspend_state_var) {
      continue;
    }

    if (variable->owner() == this) {
      if (variable->is_captured()) {
        AllocateContextVariable(variable, &context_owner);
        *found_captured_variables = true;
      } else {
        variable->set_index(next_index);
        next_index = VariableIndex(next_index.value() - 1);
      }
    }
  }
  // Allocate variables of all children.
  VariableIndex min_index = next_index;
  LocalScope* child = this->child();
  while (child != nullptr) {
    // Ignored, since no parameters.
    const VariableIndex dummy_parameter_index(0);

    // No parameters in children scopes.
    const int num_parameters_in_child = 0;
    VariableIndex child_next_index = child->AllocateVariables(
        function, dummy_parameter_index, num_parameters_in_child, next_index,
        context_owner, found_captured_variables);
    if (child_next_index.value() < min_index.value()) {
      min_index = child_next_index;
    }
    child = child->sibling();
  }
  return min_index;
}

LocalVariable::LocalVariable(TokenPosition declaration_pos,
                             TokenPosition token_pos,
                             const String& name,
                             const AbstractType& static_type,
                             intptr_t kernel_offset)
    : LocalVariable(declaration_pos,
                    token_pos,
                    name,
                    static_type,
                    kernel_offset,
                    new CompileType(CompileType::FromAbstractType(
                        static_type,
                        CompileType::kCanBeNull,
                        CompileType::kCannotBeSentinel))) {}

// The VM creates synthetic variables that start with ":" and the CFE creates
// synthetic variables with no name.
bool LocalVariable::IsFilteredIdentifier(const String& name) {
  if (name.ptr() == Symbols::Empty().ptr()) {
    return true;
  }
  if (name.ptr() == Symbols::FunctionTypeArgumentsVar().ptr()) {
    // Keep :function_type_arguments for accessing type variables in debugging.
    return false;
  }
  return name.CharAt(0) == ':';
}

LocalVarDescriptorsPtr LocalScope::GetVarDescriptors(
    const Function& func,
    ZoneGrowableArray<intptr_t>* context_level_array) {
  LocalVarDescriptorsBuilder vars;
  vars.AddDeoptIdToContextLevelMappings(context_level_array);

  // First enter all variables from scopes of outer functions.
  const ContextScope& context_scope =
      ContextScope::Handle(func.context_scope());
  if (!context_scope.IsNull()) {
    ASSERT(func.HasParent());
    for (int i = 0; i < context_scope.num_variables(); i++) {
      if (context_scope.IsInvisibleAt(i)) {
        continue;
      }
      String& name = String::Handle(context_scope.NameAt(i));
      ASSERT(!LocalVariable::IsFilteredIdentifier(name));

      LocalVarDescriptorsBuilder::VarDesc desc;
      desc.name = &name;
      desc.info.set_kind(UntaggedLocalVarDescriptors::kContextVar);
      desc.info.scope_id = context_scope.ContextLevelAt(i);
      desc.info.declaration_pos = context_scope.DeclarationTokenIndexAt(i);
      desc.info.begin_pos = begin_token_pos();
      desc.info.end_pos = end_token_pos();
      ASSERT((desc.info.begin_pos.IsReal() != desc.info.end_pos.IsReal()) ||
             (desc.info.begin_pos <= desc.info.end_pos));
      desc.info.set_index(context_scope.ContextIndexAt(i));
      vars.Add(desc);
    }
  }
  // Now collect all variables from local scopes.
  int16_t scope_id = 0;
  CollectLocalVariables(&vars, &scope_id);

  return vars.Done();
}

// Add visible variables that are declared in this scope to vars, then
// collect visible variables of children, followed by siblings.
void LocalScope::CollectLocalVariables(LocalVarDescriptorsBuilder* vars,
                                       int16_t* scope_id) {
  (*scope_id)++;
  for (int i = 0; i < this->variables_.length(); i++) {
    LocalVariable* var = variables_[i];
    if (var->owner() == this) {
      if (var->name().ptr() == Symbols::CurrentContextVar().ptr()) {
        // This is the local variable in which the function saves its
        // own context before calling a closure function.
        LocalVarDescriptorsBuilder::VarDesc desc;
        desc.name = &var->name();
        desc.info.set_kind(UntaggedLocalVarDescriptors::kSavedCurrentContext);
        desc.info.scope_id = 0;
        desc.info.declaration_pos = TokenPosition::kMinSource;
        desc.info.begin_pos = TokenPosition::kMinSource;
        desc.info.end_pos = TokenPosition::kMinSource;
        desc.info.set_index(var->index().value());
        vars->Add(desc);
      } else if (!var->is_invisible()) {
        ASSERT(!LocalVariable::IsFilteredIdentifier(var->name()));
        // This is a regular Dart variable, either stack-based or captured.
        LocalVarDescriptorsBuilder::VarDesc desc;
        desc.name = &var->name();
        if (var->is_captured()) {
          desc.info.set_kind(UntaggedLocalVarDescriptors::kContextVar);
          ASSERT(var->owner() != nullptr);
          ASSERT(var->owner()->context_level() >= 0);
          desc.info.scope_id = var->owner()->context_level();
        } else {
          desc.info.set_kind(UntaggedLocalVarDescriptors::kStackVar);
          desc.info.scope_id = *scope_id;
        }
        desc.info.set_index(var->index().value());
        desc.info.declaration_pos = var->declaration_token_pos();
        desc.info.begin_pos = var->token_pos();
        desc.info.end_pos = var->owner()->end_token_pos();
        vars->Add(desc);
      }
    }
  }
  LocalScope* child = this->child();
  while (child != nullptr) {
    child->CollectLocalVariables(vars, scope_id);
    child = child->sibling();
  }
}

LocalVariable* LocalScope::LocalLookupVariable(const String& name,
                                               intptr_t kernel_offset) const {
  ASSERT(name.IsNull() || name.IsSymbol());
  for (intptr_t i = 0; i < variables_.length(); i++) {
    LocalVariable* var = variables_[i];
    if (var->kernel_offset() == kernel_offset) {
      if (kernel_offset != LocalVariable::kNoKernelOffset) {
        // Variable from kernel.
        return var;
      } else {
        // Synthetic variable from the VM.
        ASSERT(kernel_offset == LocalVariable::kNoKernelOffset);
        ASSERT(name.IsSymbol());
        ASSERT(var->name().IsSymbol());
        if (var->name().ptr() == name.ptr()) {
          return var;
        }
      }
    }
  }
  return nullptr;
}

LocalVariable* LocalScope::LookupVariable(const String& name,
                                          intptr_t kernel_offset,
                                          bool test_only) {
  LocalScope* current_scope = this;
  while (current_scope != nullptr) {
    LocalVariable* var =
        current_scope->LocalLookupVariable(name, kernel_offset);
    // If testing only, return the variable even if invisible.
    if ((var != nullptr) && (!var->is_invisible() || test_only)) {
      if (!test_only && (var->owner()->function_level() != function_level())) {
        CaptureVariable(var);
      }
      return var;
    }
    current_scope = current_scope->parent();
  }
  return nullptr;
}

LocalVariable* LocalScope::LookupVariableByName(const String& name) {
  ASSERT(name.IsSymbol());
  for (LocalScope* scope = this; scope != nullptr; scope = scope->parent()) {
    for (intptr_t i = 0, n = scope->variables_.length(); i < n; ++i) {
      LocalVariable* var = scope->variables_[i];
      ASSERT(var->name().IsSymbol());
      if (var->name().ptr() == name.ptr()) {
        return var;
      }
    }
  }
  return nullptr;
}

void LocalScope::CaptureVariable(LocalVariable* variable) {
  ASSERT(variable != nullptr);

  // The variable must exist in an enclosing scope, not necessarily in this one.
  variable->set_is_captured();
  const int variable_function_level = variable->owner()->function_level();
  LocalScope* scope = this;
  while (scope->function_level() != variable_function_level) {
    // Insert an alias of the variable in the top scope of each function
    // level so that the variable is found in the context.
    LocalScope* parent_scope = scope->parent();
    while ((parent_scope != nullptr) &&
           (parent_scope->function_level() == scope->function_level())) {
      scope = parent_scope;
      parent_scope = scope->parent();
    }
    // An alias may already have been added in this scope, and in that case,
    // in parent scopes as needed. If so, we are done.
    if (!scope->AddVariable(variable)) {
      return;
    }
    ASSERT(variable->owner() != scope);  // Item is an alias.
    scope = parent_scope;
  }
}

int LocalScope::NumCapturedVariables() const {
  // It is not necessary to traverse parent scopes, since we are only interested
  // in the captured variables referenced in this scope. If this scope is the
  // top scope at function level 1 and it (or its children scopes) references a
  // captured variable declared in a parent scope at function level 0, it will
  // contain an alias for that variable.

  // Since code generation for nested functions is postponed until first
  // invocation, the function level of the closure scope can only be 1.
  ASSERT(function_level() == 1);

  int num_captured = 0;
  for (int i = 0; i < num_variables(); i++) {
    LocalVariable* variable = VariableAt(i);
    // Count the aliases of captured variables belonging to outer scopes.
    if (variable->owner()->function_level() != 1) {
      ASSERT(variable->is_captured());
      ASSERT(variable->owner()->function_level() == 0);
      num_captured++;
    }
  }
  return num_captured;
}

ContextScopePtr LocalScope::PreserveOuterScope(
    const Function& function,
    intptr_t current_context_level) const {
  Zone* zone = Thread::Current()->zone();
  auto& library = Library::Handle(
      zone, function.IsNull()
                ? Library::null()
                : Class::Handle(zone, function.Owner()).library());
  // Since code generation for nested functions is postponed until first
  // invocation, the function level of the closure scope can only be 1.
  ASSERT(function_level() == 1);

  // Count the number of referenced captured variables.
  intptr_t num_captured_vars = NumCapturedVariables();

  // Create a ContextScope with space for num_captured_vars descriptors.
  const ContextScope& context_scope =
      ContextScope::Handle(ContextScope::New(num_captured_vars, false));

  LocalVariable* awaiter_link = nullptr;

  // Create a descriptor for each referenced captured variable of enclosing
  // functions to preserve its name and its context allocation information.
  int captured_idx = 0;
  for (int i = 0; i < num_variables(); i++) {
    LocalVariable* variable = VariableAt(i);
    // Preserve the aliases of captured variables belonging to outer scopes.
    if (variable->owner()->function_level() != 1) {
      context_scope.SetTokenIndexAt(captured_idx, variable->token_pos());
      context_scope.SetDeclarationTokenIndexAt(
          captured_idx, variable->declaration_token_pos());
      context_scope.SetNameAt(captured_idx, variable->name());
      context_scope.ClearFlagsAt(captured_idx);
      context_scope.SetIsFinalAt(captured_idx, variable->is_final());
      context_scope.SetIsLateAt(captured_idx, variable->is_late());
      if (variable->is_late()) {
        context_scope.SetLateInitOffsetAt(captured_idx,
                                          variable->late_init_offset());
      }
      CompileType* type = variable->inferred_type();
      context_scope.SetTypeAt(captured_idx, *type->ToAbstractType());
      context_scope.SetCidAt(captured_idx, type->ToNullableCid());
      context_scope.SetIsNullableAt(captured_idx, type->is_nullable());
      context_scope.SetIsInvisibleAt(captured_idx, variable->is_invisible());
      context_scope.SetContextIndexAt(captured_idx, variable->index().value());
      // Adjust the context level relative to the current context level,
      // since the context of the current scope will be at level 0 when
      // compiling the nested function.
      intptr_t adjusted_context_level =
          variable->owner()->context_level() - current_context_level;
      context_scope.SetContextLevelAt(captured_idx, adjusted_context_level);
      context_scope.SetKernelOffsetAt(captured_idx, variable->kernel_offset());

      // Handle async frame link.
      const bool is_awaiter_link = variable->ComputeIfIsAwaiterLink(library);
      context_scope.SetIsAwaiterLinkAt(captured_idx, is_awaiter_link);
      if (is_awaiter_link) {
        awaiter_link = variable;
      }
      captured_idx++;
    }
  }
  ASSERT(context_scope.num_variables() == captured_idx);  // Verify count.

  if (awaiter_link != nullptr) {
    const intptr_t depth =
        current_context_level - awaiter_link->owner()->context_level();
    const intptr_t index = awaiter_link->index().value();
    if (Utils::IsUint(8, depth) && Utils::IsUint(8, index)) {
      function.set_awaiter_link(
          {static_cast<uint8_t>(depth), static_cast<uint8_t>(index)});
    } else if (FLAG_precompiled_mode) {
      OS::PrintErr(
          "Warning: @pragma('vm:awaiter-link') marked variable %s is visible "
          "from the function %s but the link {%" Pd ", %" Pd
          "} can't be encoded\n",
          awaiter_link->name().ToCString(),
          function.IsNull() ? "<?>" : function.ToFullyQualifiedCString(), depth,
          index);
    }
  }

  return context_scope.ptr();
}

LocalScope* LocalScope::RestoreOuterScope(const ContextScope& context_scope) {
  // The function level of the outer scope is one less than the function level
  // of the current function, which is 0.
  LocalScope* outer_scope = new LocalScope(nullptr, -1, 0);
  // Add all variables as aliases to the outer scope.
  for (int i = 0; i < context_scope.num_variables(); i++) {
    const bool is_late = context_scope.IsLateAt(i);
    const auto& static_type = AbstractType::ZoneHandle(context_scope.TypeAt(i));
    CompileType* inferred_type =
        new CompileType(context_scope.IsNullableAt(i), is_late,
                        context_scope.CidAt(i), &static_type);
    LocalVariable* variable = new LocalVariable(
        context_scope.DeclarationTokenIndexAt(i), context_scope.TokenIndexAt(i),
        String::ZoneHandle(context_scope.NameAt(i)), static_type,
        context_scope.KernelOffsetAt(i), inferred_type);
    variable->set_is_awaiter_link(context_scope.IsAwaiterLinkAt(i));
    variable->set_is_captured();
    variable->set_index(VariableIndex(context_scope.ContextIndexAt(i)));
    if (context_scope.IsFinalAt(i)) {
      variable->set_is_final();
    }
    if (is_late) {
      variable->set_is_late();
      variable->set_late_init_offset(context_scope.LateInitOffsetAt(i));
    }
    if (context_scope.IsInvisibleAt(i)) {
      variable->set_invisible(true);
    }
    // Create a fake owner scope describing the index and context level of the
    // variable. Function level and loop level are unused (set to 0), since
    // context level has already been assigned.
    LocalScope* owner_scope = new LocalScope(nullptr, 0, 0);
    owner_scope->set_context_level(context_scope.ContextLevelAt(i));
    owner_scope->AddVariable(variable);
    outer_scope->AddVariable(variable);  // As alias.
    ASSERT(variable->owner() == owner_scope);
  }
  return outer_scope;
}

ContextScopePtr LocalScope::CreateImplicitClosureScope(const Function& func) {
  const intptr_t kNumCapturedVars = 1;

  // Create a ContextScope with space for kNumCapturedVars descriptors.
  const ContextScope& context_scope =
      ContextScope::Handle(ContextScope::New(kNumCapturedVars, true));

  // Create a descriptor for 'this' variable.
  context_scope.SetTokenIndexAt(0, func.token_pos());
  context_scope.SetDeclarationTokenIndexAt(0, func.token_pos());
  context_scope.SetNameAt(0, Symbols::This());
  context_scope.ClearFlagsAt(0);
  context_scope.SetIsFinalAt(0, true);
  const AbstractType& type = AbstractType::Handle(func.ParameterTypeAt(0));
  context_scope.SetTypeAt(0, type);
  context_scope.SetCidAt(0, kIllegalCid);
  context_scope.SetContextIndexAt(0, 0);
  context_scope.SetContextLevelAt(0, 0);
  context_scope.SetKernelOffsetAt(0, LocalVariable::kNoKernelOffset);
  ASSERT(context_scope.num_variables() == kNumCapturedVars);  // Verify count.
  return context_scope.ptr();
}

static void PrintIndentation(BaseTextBuffer* f, int depth) {
  for (int i = 0; i < depth; i++) {
    f->AddString("  ");
  }
}

void LocalScope::PrintTo(BaseTextBuffer* f, int depth) const {
  PrintIndentation(f, depth);
  f->AddString("scope: ");
  f->Printf("function_level: %i, ", function_level_);
  f->Printf("loop_level: %i, ", loop_level_);
  if (context_level_ == kUninitializedContextLevel) {
    f->AddString("context_level: uninitialized, ");
  } else {
    f->Printf("context_level: %i, ", context_level_);
  }
  int num_variables_ = num_variables();
  f->Printf("variables: %i, ", num_variables_);
  f->Printf("context_variables: %i", num_context_variables());
  if (function_level() == 1) {
    f->Printf(", captured_variables: %i", NumCapturedVariables());
  }
  f->AddString("\n");

  for (intptr_t i = 0; i < num_variables_; i++) {
    LocalVariable* variable = VariableAt(i);
    variable->PrintTo(f, "variable", depth + 1, this);
  }

  for (intptr_t i = 0; i < num_context_variables(); i++) {
    LocalVariable* variable = context_variables().At(i);
    variable->PrintTo(f, "context variable", depth + 1, this);
  }

  auto* child = child_;
  while (child != nullptr) {
    child->PrintTo(f, depth + 1);
    child = child->sibling();
  }
}

const char* LocalScope::ToCString() const {
  char buffer[1024];
  BufferFormatter f(buffer, sizeof(buffer));
  PrintTo(&f);
  return Thread::Current()->zone()->MakeCopyOfString(buffer);
}

void LocalVariable::PrintTo(BaseTextBuffer* f,
                            const char* label,
                            int depth,
                            const LocalScope* scope) const {
  PrintIndentation(f, depth);
  f->Printf("%s: ", label);
  const char* var_name = name().ToCString();
  if (var_name[0] == '\0') {
    // Follow CFE no-name variable printing convention.
    var_name = "#t?";
  }
  f->Printf("%s, ", var_name);
  f->Printf("kernel_offset: %" Pd ", ", kernel_offset());
  if (HasIndex()) {
    auto index_value = index().value();
    if (index().value() == VariableIndex::kInvalidIndex) {
      f->AddString("index: invalid");
    } else {
      f->Printf("index: %i", index_value);
    }
  } else {
    f->AddString("index: none");
  }
  if (is_captured()) {
    f->AddString(", is_captured");
  }
  if (is_captured_parameter()) {
    f->AddString(", is_captured_parameter");
  }
  if (is_invisible()) {
    f->AddString(", is_invisible");
  }
  if (scope != nullptr && owner() != scope) {
    f->AddString(" (not owner)");
  }
  f->AddString("\n");
}

const char* LocalVariable::ToCString() const {
  char buffer[1024];
  BufferFormatter f(buffer, sizeof(buffer));
  PrintTo(&f);
  return Thread::Current()->zone()->MakeCopyOfString(buffer);
}

bool LocalVariable::ComputeIfIsAwaiterLink(const Library& library) {
  if (is_awaiter_link_ == IsAwaiterLink::kUnknown) {
    RELEASE_ASSERT(annotations_offset_ != kNoKernelOffset);
    Thread* T = Thread::Current();
    Zone* Z = T->zone();
    const auto& metadata = Object::Handle(
        Z, kernel::EvaluateMetadata(library, annotations_offset_,
                                    /* is_annotations_offset = */ true));
    set_is_awaiter_link(
        FindPragmaInMetadata(T, metadata, Symbols::vm_awaiter_link()));
  }
  return is_awaiter_link_ == IsAwaiterLink::kLink;
}

bool LocalVariable::Equals(const LocalVariable& other) const {
  if (HasIndex() && other.HasIndex() && (index() == other.index())) {
    if (is_captured() == other.is_captured()) {
      if (!is_captured()) {
        return true;
      }
      if (owner()->context_level() == other.owner()->context_level()) {
        return true;
      }
    }
  }
  return false;
}

void LocalVarDescriptorsBuilder::AddAll(Zone* zone,
                                        const LocalVarDescriptors& var_descs) {
  for (intptr_t i = 0, n = var_descs.Length(); i < n; ++i) {
    VarDesc desc;
    desc.name = &String::Handle(zone, var_descs.GetName(i));
    var_descs.GetInfo(i, &desc.info);
    Add(desc);
  }
}

void LocalVarDescriptorsBuilder::AddDeoptIdToContextLevelMappings(
    ZoneGrowableArray<intptr_t>* context_level_array) {
  // Record deopt-id -> context-level mappings, using ranges of deopt-ids with
  // the same context-level. [context_level_array] contains (deopt_id,
  // context_level) tuples.
  for (intptr_t start = 0; start < context_level_array->length();) {
    intptr_t start_deopt_id = (*context_level_array)[start];
    intptr_t start_context_level = (*context_level_array)[start + 1];
    intptr_t end = start;
    intptr_t end_deopt_id = start_deopt_id;
    for (intptr_t peek = start + 2; peek < context_level_array->length();
         peek += 2) {
      intptr_t peek_deopt_id = (*context_level_array)[peek];
      intptr_t peek_context_level = (*context_level_array)[peek + 1];
      // The range encoding assumes the tuples have ascending deopt_ids.
      ASSERT(peek_deopt_id > end_deopt_id);
      if (peek_context_level != start_context_level) break;
      end = peek;
      end_deopt_id = peek_deopt_id;
    }

    VarDesc desc;
    desc.name = &Symbols::Empty();  // No name.
    desc.info.set_kind(UntaggedLocalVarDescriptors::kContextLevel);
    desc.info.scope_id = 0;
    // We repurpose the token position fields to store deopt IDs in this case.
    desc.info.begin_pos = TokenPosition::Deserialize(start_deopt_id);
    desc.info.end_pos = TokenPosition::Deserialize(end_deopt_id);
    desc.info.set_index(start_context_level);
    Add(desc);

    start = end + 2;
  }
}

LocalVarDescriptorsPtr LocalVarDescriptorsBuilder::Done() {
  if (vars_.is_empty()) {
    return Object::empty_var_descriptors().ptr();
  }
  const LocalVarDescriptors& var_desc =
      LocalVarDescriptors::Handle(LocalVarDescriptors::New(vars_.length()));
  for (int i = 0; i < vars_.length(); i++) {
    var_desc.SetVar(i, *(vars_[i].name), &vars_[i].info);
  }
  return var_desc.ptr();
}

}  // namespace dart

#endif  // !defined(DART_PRECOMPILED_RUNTIME)
