// 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_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)
