// 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/object.h"
#include "vm/object_store.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_(NULL),
      sibling_(NULL),
      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 != NULL) && (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 != NULL) {
    if (current_scope == scope) {
      return true;
    }
    current_scope = current_scope->parent();
  }
  return false;
}

bool LocalScope::AddVariable(LocalVariable* variable) {
  ASSERT(variable != NULL);
  if (LocalLookupVariable(variable->name()) != NULL) {
    return false;
  }
  variables_.Add(variable);
  if (variable->owner() == NULL) {
    // 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 != NULL);
  if (LocalLookupVariable(parameter->name()) != NULL) {
    return false;
  }
  variables_.InsertAt(pos, parameter);
  // InsertParameterAt is not used to add aliases of parameters.
  ASSERT(parameter->owner() == NULL);
  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) == NULL) {
    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* await_jump_var = nullptr;
  LocalVariable* async_future = nullptr;
  LocalVariable* controller = nullptr;
  LocalVariable* chained_future = nullptr;
  LocalVariable* is_sync = nullptr;
  for (intptr_t i = 0; i < num_variables(); i++) {
    LocalVariable* variable = VariableAt(i);
    if (variable->owner() == this) {
      if (variable->is_captured()) {
        if (variable->name().Equals(Symbols::AwaitJumpVar())) {
          await_jump_var = variable;
        } else if (variable->name().Equals(Symbols::AsyncFuture())) {
          async_future = variable;
        } else if (variable->name().Equals(Symbols::Controller())) {
          controller = variable;
        } else if (variable->is_chained_future()) {
          chained_future = variable;
        } else if (variable->name().Equals(Symbols::is_sync())) {
          is_sync = variable;
        }
      }
    }
  }
  // If we are in an async/async* function, force :await_jump_var and
  // :async_future to be at fixed locations in the slot.
  if (await_jump_var != nullptr) {
    AllocateContextVariable(await_jump_var, &context_owner);
    *found_captured_variables = true;
    ASSERT(await_jump_var->index().value() == Context::kAwaitJumpVarIndex);
  }
  if (async_future != nullptr) {
    AllocateContextVariable(async_future, &context_owner);
    *found_captured_variables = true;
    ASSERT(async_future->index().value() == Context::kAsyncFutureIndex);
  }
  if (controller != nullptr) {
    AllocateContextVariable(controller, &context_owner);
    *found_captured_variables = true;
    ASSERT(controller->index().value() == Context::kControllerIndex);
  }
  if (chained_future != nullptr) {
    AllocateContextVariable(chained_future, &context_owner);
    *found_captured_variables = true;
    // Remember context indices of _future variables in _Future.timeout and
    // Future.wait. They are used while collecting async stack traces.
    if (function.recognized_kind() == MethodRecognizer::kFutureTimeout) {
#ifdef DEBUG
      auto old_value = IsolateGroup::Current()
                           ->object_store()
                           ->future_timeout_future_index();
      ASSERT(old_value == Object::null() ||
             Smi::Value(old_value) == chained_future->index().value());
#endif  // DEBUG
      IsolateGroup::Current()->object_store()->set_future_timeout_future_index(
          Smi::Handle(Smi::New(chained_future->index().value())));
    } else if (function.recognized_kind() == MethodRecognizer::kFutureWait) {
#ifdef DEBUG
      auto old_value =
          IsolateGroup::Current()->object_store()->future_wait_future_index();
      ASSERT(old_value == Object::null() ||
             Smi::Value(old_value) == chained_future->index().value());
#endif  // DEBUG
      IsolateGroup::Current()->object_store()->set_future_wait_future_index(
          Smi::Handle(Smi::New(chained_future->index().value())));
    } else {
      UNREACHABLE();
    }
  }
  if (is_sync != nullptr) {
    AllocateContextVariable(is_sync, &context_owner);
    *found_captured_variables = true;
    ASSERT(is_sync->index().value() == Context::kIsSyncIndex);
  }

  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;
  while (pos < num_variables()) {
    LocalVariable* variable = VariableAt(pos);
    if (variable->owner() == this) {
      if (variable->is_captured()) {
        // Skip the variables already pre-allocated above.
        if (variable != await_jump_var && variable != async_future &&
            variable != controller && variable != chained_future &&
            variable != is_sync) {
          AllocateContextVariable(variable, &context_owner);
          *found_captured_variables = true;
        }
      } else {
        variable->set_index(next_index);
        next_index = VariableIndex(next_index.value() - 1);
      }
    }
    pos++;
  }
  // Allocate variables of all children.
  VariableIndex min_index = next_index;
  LocalScope* child = this->child();
  while (child != NULL) {
    // 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;
}

// The parser creates internal variables that start with ":"
static bool IsFilteredIdentifier(const String& str) {
  ASSERT(str.Length() > 0);
  if (str.ptr() == Symbols::AsyncOperation().ptr()) {
    // Keep :async_op for asynchronous debugging.
    return false;
  }
  if (str.ptr() == Symbols::AsyncFuture().ptr()) {
    // Keep :async_future for asynchronous debugging.
    return false;
  }
  if (str.ptr() == Symbols::ControllerStream().ptr()) {
    // Keep :controller_stream for asynchronous debugging.
    return false;
  }
  if (str.ptr() == Symbols::AwaitJumpVar().ptr()) {
    // Keep :await_jump_var for asynchronous debugging.
    return false;
  }
  if (str.ptr() == Symbols::is_sync().ptr()) {
    // Keep :is_sync for asynchronous debugging.
    return false;
  }
  if (str.ptr() == Symbols::FunctionTypeArgumentsVar().ptr()) {
    // Keep :function_type_arguments for accessing type variables in debugging.
    return false;
  }
  return str.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++) {
      String& name = String::Handle(context_scope.NameAt(i));
      UntaggedLocalVarDescriptors::VarInfoKind kind;
      if (!IsFilteredIdentifier(name)) {
        kind = UntaggedLocalVarDescriptors::kContextVar;
      } else {
        continue;
      }

      LocalVarDescriptorsBuilder::VarDesc desc;
      desc.name = &name;
      desc.info.set_kind(kind);
      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) && !var->is_invisible()) {
      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 (!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() != NULL);
          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 != NULL) {
    child->CollectLocalVariables(vars, scope_id);
    child = child->sibling();
  }
}

LocalVariable* LocalScope::LocalLookupVariable(const String& name) const {
  ASSERT(name.IsSymbol());
  for (intptr_t i = 0; i < variables_.length(); i++) {
    LocalVariable* var = variables_[i];
    ASSERT(var->name().IsSymbol());
    if (var->name().ptr() == name.ptr()) {
      return var;
    }
  }
  return NULL;
}

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

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

  // 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 != NULL) &&
           (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(
    int current_context_level) const {
  // 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));

  // 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());
      }
      context_scope.SetIsConstAt(captured_idx, variable->IsConst());
      if (variable->IsConst()) {
        context_scope.SetConstValueAt(captured_idx, *variable->ConstValue());
      } else {
        context_scope.SetTypeAt(captured_idx, variable->type());
      }
      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.
      int adjusted_context_level =
          variable->owner()->context_level() - current_context_level;
      context_scope.SetContextLevelAt(captured_idx, adjusted_context_level);
      captured_idx++;
    }
  }
  ASSERT(context_scope.num_variables() == captured_idx);  // Verify count.
  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(NULL, -1, 0);
  // Add all variables as aliases to the outer scope.
  for (int i = 0; i < context_scope.num_variables(); i++) {
    LocalVariable* variable;
    if (context_scope.IsConstAt(i)) {
      variable = new LocalVariable(context_scope.DeclarationTokenIndexAt(i),
                                   context_scope.TokenIndexAt(i),
                                   String::ZoneHandle(context_scope.NameAt(i)),
                                   Object::dynamic_type());
      variable->SetConstValue(
          Instance::ZoneHandle(context_scope.ConstValueAt(i)));
    } else {
      variable =
          new LocalVariable(context_scope.DeclarationTokenIndexAt(i),
                            context_scope.TokenIndexAt(i),
                            String::ZoneHandle(context_scope.NameAt(i)),
                            AbstractType::ZoneHandle(context_scope.TypeAt(i)));
    }
    variable->set_is_captured();
    variable->set_index(VariableIndex(context_scope.ContextIndexAt(i)));
    if (context_scope.IsFinalAt(i)) {
      variable->set_is_final();
    }
    if (context_scope.IsLateAt(i)) {
      variable->set_is_late();
      variable->set_late_init_offset(context_scope.LateInitOffsetAt(i));
    }
    // 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(NULL, 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;
}

void LocalScope::CaptureLocalVariables(LocalScope* top_scope) {
  ASSERT(top_scope->function_level() == function_level());
  LocalScope* scope = this;
  while (scope != top_scope->parent()) {
    for (intptr_t i = 0; i < scope->num_variables(); i++) {
      LocalVariable* variable = scope->VariableAt(i);
      if (variable->is_forced_stack() ||
          (variable->name().ptr() == Symbols::ExceptionVar().ptr()) ||
          (variable->name().ptr() == Symbols::SavedTryContextVar().ptr()) ||
          (variable->name().ptr() == Symbols::ArgDescVar().ptr()) ||
          (variable->name().ptr() ==
           Symbols::FunctionTypeArgumentsVar().ptr())) {
        // Don't capture those variables because the VM expects them to be on
        // the stack.
        continue;
      }
      scope->CaptureVariable(variable);
    }
    scope = scope->parent();
  }
}

ContextScopePtr LocalScope::CreateImplicitClosureScope(const Function& func) {
  static 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);
  context_scope.SetIsConstAt(0, false);
  const AbstractType& type = AbstractType::Handle(func.ParameterTypeAt(0));
  context_scope.SetTypeAt(0, type);
  context_scope.SetContextIndexAt(0, 0);
  context_scope.SetContextLevelAt(0, 0);
  ASSERT(context_scope.num_variables() == kNumCapturedVars);  // Verify count.
  return context_scope.ptr();
}

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)
