// Copyright (c) 2018, 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.

#include "vm/compiler/frontend/constant_evaluator.h"

#include "vm/compiler/aot/precompiler.h"
#include "vm/compiler/frontend/kernel_to_il.h"
#include "vm/compiler/jit/compiler.h"
#include "vm/dart_entry.h"
#include "vm/longjump.h"
#include "vm/object_store.h"

#if !defined(DART_PRECOMPILED_RUNTIME)

namespace dart {
namespace kernel {

#define Z (zone_)
#define H (translation_helper_)
#define T (type_translator_)
#define I Isolate::Current()

ConstantEvaluator::ConstantEvaluator(KernelReaderHelper* helper,
                                     TypeTranslator* type_translator,
                                     ActiveClass* active_class,
                                     FlowGraphBuilder* flow_graph_builder)
    : helper_(helper),
      isolate_(Isolate::Current()),
      zone_(helper->zone_),
      translation_helper_(helper->translation_helper_),
      type_translator_(*type_translator),
      active_class_(active_class),
      flow_graph_builder_(flow_graph_builder),
      script_(helper->script()),
      result_(Instance::Handle(zone_)) {}

bool ConstantEvaluator::IsCached(intptr_t offset) {
  return GetCachedConstant(offset, &result_);
}

RawInstance* ConstantEvaluator::EvaluateExpression(intptr_t offset,
                                                   bool reset_position) {
  ASSERT(Error::Handle(Z, H.thread()->sticky_error()).IsNull());
  if (!GetCachedConstant(offset, &result_)) {
    BailoutIfBackgroundCompilation();

    ASSERT(IsAllowedToEvaluate());
    intptr_t original_offset = helper_->ReaderOffset();
    helper_->SetOffset(offset);
    uint8_t payload = 0;
    Tag tag = helper_->ReadTag(&payload);  // read tag.
    switch (tag) {
      case kVariableGet:
        EvaluateVariableGet(/* is_specialized = */ false);
        break;
      case kSpecializedVariableGet:
        EvaluateVariableGet(/* is_specialized = */ true);
        break;
      case kPropertyGet:
        EvaluatePropertyGet();
        break;
      case kDirectPropertyGet:
        EvaluateDirectPropertyGet();
        break;
      case kStaticGet:
        EvaluateStaticGet();
        break;
      case kMethodInvocation:
        EvaluateMethodInvocation();
        break;
      case kDirectMethodInvocation:
        EvaluateDirectMethodInvocation();
        break;
      case kSuperMethodInvocation:
        EvaluateSuperMethodInvocation();
        break;
      case kStaticInvocation:
      case kConstStaticInvocation:
        EvaluateStaticInvocation();
        break;
      case kConstConstructorInvocation:
        EvaluateConstructorInvocationInternal();
        break;
      case kNot:
        EvaluateNot();
        break;
      case kLogicalExpression:
        EvaluateLogicalExpression();
        break;
      case kConditionalExpression:
        EvaluateConditionalExpression();
        break;
      case kStringConcatenation:
        EvaluateStringConcatenation();
        break;
      case kListConcatenation:
      case kSetConcatenation:
      case kMapConcatenation:
        // These only occur inside unevaluated constants, so if we decide to
        // remove support for late evaluation of environment constants from
        // dill files in the VM, an implementation here will not be necessary.
        UNIMPLEMENTED();
        break;
      case kSymbolLiteral:
        EvaluateSymbolLiteral();
        break;
      case kTypeLiteral:
        EvaluateTypeLiteral();
        break;
      case kAsExpression:
        EvaluateAsExpression();
        break;
      case kConstListLiteral:
        EvaluateListLiteralInternal();
        break;
      case kConstSetLiteral:
        // Set literals are currently desugared in the frontend and will not
        // reach the VM. See http://dartbug.com/35124 for discussion.
        UNREACHABLE();
        break;
      case kConstMapLiteral:
        EvaluateMapLiteralInternal();
        break;
      case kLet:
        EvaluateLet();
        break;
      case kBlockExpression: {
        UNIMPLEMENTED();
        break;
      }
      case kInstantiation:
        EvaluatePartialTearoffInstantiation();
        break;
      case kBigIntLiteral:
        EvaluateBigIntLiteral();
        break;
      case kStringLiteral:
        EvaluateStringLiteral();
        break;
      case kSpecializedIntLiteral:
        EvaluateIntLiteral(payload);
        break;
      case kNegativeIntLiteral:
        EvaluateIntLiteral(true);
        break;
      case kPositiveIntLiteral:
        EvaluateIntLiteral(false);
        break;
      case kDoubleLiteral:
        EvaluateDoubleLiteral();
        break;
      case kTrueLiteral:
        EvaluateBoolLiteral(true);
        break;
      case kFalseLiteral:
        EvaluateBoolLiteral(false);
        break;
      case kNullLiteral:
        EvaluateNullLiteral();
        break;
      case kConstantExpression:
        EvaluateConstantExpression();
        break;
      default:
        H.ReportError(
            script_, TokenPosition::kNoSource,
            "Not a constant expression: unexpected kernel tag %s (%d)",
            Reader::TagName(tag), tag);
    }

    CacheConstantValue(offset, result_);
    if (reset_position) helper_->SetOffset(original_offset);
  } else {
    if (!reset_position) {
      helper_->SetOffset(offset);
      helper_->SkipExpression();
    }
  }
  return result_.raw();
}

Instance& ConstantEvaluator::EvaluateListLiteral(intptr_t offset,
                                                 bool reset_position) {
  if (!GetCachedConstant(offset, &result_)) {
    BailoutIfBackgroundCompilation();

    ASSERT(IsAllowedToEvaluate());
    intptr_t original_offset = helper_->ReaderOffset();
    helper_->SetOffset(offset);
    helper_->ReadTag();  // skip tag.
    EvaluateListLiteralInternal();

    CacheConstantValue(offset, result_);
    if (reset_position) helper_->SetOffset(original_offset);
  }
  // We return a new `ZoneHandle` here on purpose: The intermediate language
  // instructions do not make a copy of the handle, so we do it.
  return Instance::ZoneHandle(Z, result_.raw());
}

Instance& ConstantEvaluator::EvaluateMapLiteral(intptr_t offset,
                                                bool reset_position) {
  if (!GetCachedConstant(offset, &result_)) {
    BailoutIfBackgroundCompilation();

    ASSERT(IsAllowedToEvaluate());
    intptr_t original_offset = helper_->ReaderOffset();
    helper_->SetOffset(offset);
    helper_->ReadTag();  // skip tag.
    EvaluateMapLiteralInternal();

    CacheConstantValue(offset, result_);
    if (reset_position) helper_->SetOffset(original_offset);
  }
  // We return a new `ZoneHandle` here on purpose: The intermediate language
  // instructions do not make a copy of the handle, so we do it.
  return Instance::ZoneHandle(Z, result_.raw());
}

Instance& ConstantEvaluator::EvaluateConstructorInvocation(
    intptr_t offset,
    bool reset_position) {
  if (!GetCachedConstant(offset, &result_)) {
    BailoutIfBackgroundCompilation();

    ASSERT(IsAllowedToEvaluate());
    intptr_t original_offset = helper_->ReaderOffset();
    helper_->SetOffset(offset);
    helper_->ReadTag();  // skip tag.
    EvaluateConstructorInvocationInternal();

    CacheConstantValue(offset, result_);
    if (reset_position) helper_->SetOffset(original_offset);
  }
  // We return a new `ZoneHandle` here on purpose: The intermediate language
  // instructions do not make a copy of the handle, so we do it.
  return Instance::ZoneHandle(Z, result_.raw());
}

Instance& ConstantEvaluator::EvaluateStaticInvocation(intptr_t offset,
                                                      bool reset_position) {
  if (!GetCachedConstant(offset, &result_)) {
    BailoutIfBackgroundCompilation();

    ASSERT(IsAllowedToEvaluate());
    intptr_t original_offset = helper_->ReaderOffset();
    helper_->SetOffset(offset);
    helper_->ReadTag();  // skip tag.
    EvaluateStaticInvocation();

    CacheConstantValue(offset, result_);
    if (reset_position) helper_->SetOffset(original_offset);
  }
  // We return a new `ZoneHandle` here on purpose: The intermediate language
  // instructions do not make a copy of the handle, so we do it.
  return Instance::ZoneHandle(Z, result_.raw());
}

RawObject* ConstantEvaluator::EvaluateExpressionSafe(intptr_t offset) {
  LongJumpScope jump;
  if (setjmp(*jump.Set()) == 0) {
    return EvaluateExpression(offset);
  } else {
    return H.thread()->StealStickyError();
  }
}

RawObject* ConstantEvaluator::EvaluateAnnotations() {
  intptr_t list_length = helper_->ReadListLength();  // read list length.
  const Array& metadata_values =
      Array::Handle(Z, Array::New(list_length, H.allocation_space()));
  Instance& value = Instance::Handle(Z);
  for (intptr_t i = 0; i < list_length; ++i) {
    // this will (potentially) read the expression, but reset the position.
    value = EvaluateExpression(helper_->ReaderOffset());
    helper_->SkipExpression();  // read (actual) initializer.
    metadata_values.SetAt(i, value);
  }
  return metadata_values.raw();
}

void ConstantEvaluator::BailoutIfBackgroundCompilation() {
  if (Compiler::IsBackgroundCompilation()) {
    Compiler::AbortBackgroundCompilation(
        DeoptId::kNone, "Cannot evaluate annotations in background compiler.");
  }
}

bool ConstantEvaluator::IsBuildingFlowGraph() const {
  return flow_graph_builder_ != nullptr;
}

bool ConstantEvaluator::IsAllowedToEvaluate() const {
  return FLAG_precompiled_mode || !IsBuildingFlowGraph() ||
         !flow_graph_builder_->optimizing_;
}

void ConstantEvaluator::EvaluateVariableGet(bool is_specialized) {
  ASSERT(IsBuildingFlowGraph());
  // When we see a [VariableGet] the corresponding [VariableDeclaration] must've
  // been executed already. It therefore must have a constant object associated
  // with it.
  const TokenPosition position = helper_->ReadPosition();  // read position.
  const intptr_t variable_kernel_position =
      helper_->ReadUInt();  // read kernel position.
  if (!is_specialized) {
    helper_->ReadUInt();              // read relative variable index.
    helper_->SkipOptionalDartType();  // read promoted type.
  }
  LocalVariable* variable =
      flow_graph_builder_->LookupVariable(variable_kernel_position);
  if (!variable->IsConst()) {
    H.ReportError(script_, position, "Not a constant expression.");
  }
  result_ = variable->ConstValue()->raw();
}

void ConstantEvaluator::EvaluateGetStringLength(intptr_t expression_offset,
                                                TokenPosition position) {
  EvaluateExpression(expression_offset);
  if (result_.IsString()) {
    const String& str = String::Handle(Z, String::RawCast(result_.raw()));
    result_ = Integer::New(str.Length(), H.allocation_space());
  } else {
    H.ReportError(
        script_, position,
        "Constant expressions can only call 'length' on string constants.");
  }
}

void ConstantEvaluator::EvaluatePropertyGet() {
  const TokenPosition position = helper_->ReadPosition();  // read position.
  intptr_t expression_offset = helper_->ReaderOffset();
  helper_->SkipExpression();                            // read receiver.
  StringIndex name = helper_->ReadNameAsStringIndex();  // read name.
  helper_->SkipCanonicalNameReference();  // read interface_target_reference.

  if (H.StringEquals(name, "length")) {
    EvaluateGetStringLength(expression_offset, position);
  } else {
    H.ReportError(
        script_, position,
        "Constant expressions can only call 'length' on string constants.");
  }
}

void ConstantEvaluator::EvaluateDirectPropertyGet() {
  TokenPosition position = helper_->ReadPosition();  // read position.
  intptr_t expression_offset = helper_->ReaderOffset();
  helper_->SkipExpression();  // read receiver.
  NameIndex kernel_name =
      helper_->ReadCanonicalNameReference();  // read target_reference.

  // TODO(vegorov): add check based on the complete canonical name.
  if (H.IsGetter(kernel_name) &&
      H.StringEquals(H.CanonicalNameString(kernel_name), "length")) {
    EvaluateGetStringLength(expression_offset, position);
  } else {
    H.ReportError(
        script_, position,
        "Constant expressions can only call 'length' on string constants.");
  }
}

void ConstantEvaluator::EvaluateStaticGet() {
  TokenPosition position = helper_->ReadPosition();  // read position.
  NameIndex target =
      helper_->ReadCanonicalNameReference();  // read target_reference.

  ASSERT(Error::Handle(Z, H.thread()->sticky_error()).IsNull());

  if (H.IsField(target)) {
    const Field& field = Field::Handle(Z, H.LookupFieldByKernelField(target));
    if (!field.is_const()) {
      H.ReportError(script_, position, "Not a constant field.");
    }
    if (field.StaticValue() == Object::transition_sentinel().raw()) {
      if (IsBuildingFlowGraph()) {
        flow_graph_builder_->InlineBailout(
            "kernel::ConstantEvaluator::EvaluateStaticGet::Cyclic");
      }
      H.ReportError(script_, position, "Not a constant expression.");
    } else if (field.StaticValue() == Object::sentinel().raw()) {
      field.SetStaticValue(Object::transition_sentinel());
      const Object& value =
          Object::Handle(Compiler::EvaluateStaticInitializer(field));
      if (value.IsError()) {
        field.SetStaticValue(Object::null_instance());
        H.ReportError(Error::Cast(value), script_, position,
                      "Not a constant expression.");
        UNREACHABLE();
      }
      Thread* thread = H.thread();
      const Error& error =
          Error::Handle(thread->zone(), thread->StealStickyError());
      if (!error.IsNull()) {
        field.SetStaticValue(Object::null_instance());
        H.ReportError(error, script_, position, "Not a constant expression.");
        UNREACHABLE();
      }
      ASSERT(value.IsNull() || value.IsInstance());
      field.SetStaticValue(value.IsNull() ? Instance::null_instance()
                                          : Instance::Cast(value));

      result_ = field.StaticValue();
      result_ = H.Canonicalize(result_);
      field.SetStaticValue(result_, true);
    } else {
      result_ = field.StaticValue();
    }
  } else if (H.IsProcedure(target)) {
    const Function& function =
        Function::ZoneHandle(Z, H.LookupStaticMethodByKernelProcedure(target));

    if (H.IsMethod(target)) {
      Function& closure_function =
          Function::ZoneHandle(Z, function.ImplicitClosureFunction());
      result_ = closure_function.ImplicitStaticClosure();
      result_ = H.Canonicalize(result_);
    } else if (H.IsGetter(target)) {
      H.ReportError(script_, position, "Not a constant expression.");
    } else {
      H.ReportError(script_, position, "Not a constant expression.");
    }
  }
}

void ConstantEvaluator::EvaluateMethodInvocation() {
  TokenPosition position = helper_->ReadPosition();  // read position.
  // This method call wasn't cached, so receiver et al. isn't cached either.
  const Instance& receiver = Instance::Handle(
      Z, EvaluateExpression(helper_->ReaderOffset(), false));  // read receiver.
  Class& klass =
      Class::Handle(Z, isolate_->class_table()->At(receiver.GetClassId()));
  ASSERT(!klass.IsNull());

  // Search the superclass chain for the selector.
  const String& method_name = helper_->ReadNameAsMethodName();  // read name.
  Function& function =
      Function::Handle(Z, H.LookupDynamicFunction(klass, method_name));

  // The frontend should guarantee that [MethodInvocation]s inside constant
  // expressions are always valid.
  ASSERT(!function.IsNull());

  // Read arguments, run the method and canonicalize the result.
  const Object& result = RunMethodCall(position, function, &receiver);
  result_ ^= result.raw();
  result_ = H.Canonicalize(result_);

  helper_->SkipCanonicalNameReference();  // read interface_target_reference.
}

void ConstantEvaluator::EvaluateDirectMethodInvocation() {
  TokenPosition position = helper_->ReadPosition();  // read position.

  const Instance& receiver = Instance::Handle(
      Z, EvaluateExpression(helper_->ReaderOffset(), false));  // read receiver.

  NameIndex kernel_name =
      helper_->ReadCanonicalNameReference();  // read target_reference.

  const Function& function = Function::ZoneHandle(
      Z, H.LookupMethodByMember(kernel_name, H.DartProcedureName(kernel_name)));

  // Read arguments, run the method and canonicalize the result.
  const Object& result = RunMethodCall(position, function, &receiver);
  result_ ^= result.raw();
  result_ = H.Canonicalize(result_);
}

void ConstantEvaluator::EvaluateSuperMethodInvocation() {
  ASSERT(IsBuildingFlowGraph());
  TokenPosition position = helper_->ReadPosition();  // read position.

  const LocalVariable* receiver_variable =
      flow_graph_builder_->parsed_function_->receiver_var();
  ASSERT(receiver_variable->IsConst());
  const Instance& receiver =
      Instance::Handle(Z, receiver_variable->ConstValue()->raw());
  ASSERT(!receiver.IsNull());

  Class& klass = Class::Handle(Z, active_class_->klass->SuperClass());
  ASSERT(!klass.IsNull());

  const String& method_name = helper_->ReadNameAsMethodName();  // read name.
  Function& function =
      Function::Handle(Z, H.LookupDynamicFunction(klass, method_name));

  // The frontend should guarantee that [MethodInvocation]s inside constant
  // expressions are always valid.
  ASSERT(!function.IsNull());

  // Read arguments, run the method and canonicalize the result.
  const Object& result = RunMethodCall(position, function, &receiver);
  result_ ^= result.raw();
  result_ = H.Canonicalize(result_);

  helper_->SkipCanonicalNameReference();  // read interface_target_reference.
}

void ConstantEvaluator::EvaluateStaticInvocation() {
  TokenPosition position = helper_->ReadPosition();  // read position.
  NameIndex procedure_reference =
      helper_->ReadCanonicalNameReference();  // read procedure reference.

  const Function& function = Function::ZoneHandle(
      Z, H.LookupStaticMethodByKernelProcedure(procedure_reference));
  Class& klass = Class::Handle(Z, function.Owner());

  intptr_t argument_count =
      helper_->ReadUInt();  // read arguments part #1: arguments count.

  // Build the type arguments vector (if necessary).
  const TypeArguments* type_arguments =
      TranslateTypeArguments(function, &klass);  // read argument types.

  // read positional and named parameters.
  const Object& result =
      RunFunction(position, function, argument_count, NULL, type_arguments);
  result_ ^= result.raw();
  result_ = H.Canonicalize(result_);
}

void ConstantEvaluator::EvaluateConstructorInvocationInternal() {
  TokenPosition position = helper_->ReadPosition();  // read position.

  NameIndex target = helper_->ReadCanonicalNameReference();  // read target.
  const Function& constructor =
      Function::Handle(Z, H.LookupConstructorByKernelConstructor(target));
  Class& klass = Class::Handle(Z, constructor.Owner());

  intptr_t argument_count =
      helper_->ReadUInt();  // read arguments part #1: arguments count.

  // Build the type arguments vector (if necessary).
  const TypeArguments* type_arguments =
      TranslateTypeArguments(constructor, &klass);  // read argument types.

  if (klass.NumTypeArguments() > 0 && !klass.IsGeneric()) {
    Type& type = Type::ZoneHandle(Z, T.ReceiverType(klass).raw());
    // TODO(27590): Can we move this code into [ReceiverType]?
    type ^= ClassFinalizer::FinalizeType(*active_class_->klass, type,
                                         ClassFinalizer::kFinalize);
    TypeArguments& canonicalized_type_arguments =
        TypeArguments::ZoneHandle(Z, type.arguments());
    canonicalized_type_arguments = canonicalized_type_arguments.Canonicalize();
    type_arguments = &canonicalized_type_arguments;
  }

  // Prepare either the instance or the type argument vector for the constructor
  // call.
  Instance* receiver = NULL;
  const TypeArguments* type_arguments_argument = NULL;
  if (!constructor.IsFactory()) {
    receiver = &Instance::Handle(Z, Instance::New(klass, Heap::kOld));
    if (type_arguments != NULL) {
      receiver->SetTypeArguments(*type_arguments);
    }
  } else {
    type_arguments_argument = type_arguments;
  }

  // read positional and named parameters.
  const Object& result = RunFunction(position, constructor, argument_count,
                                     receiver, type_arguments_argument);

  if (constructor.IsFactory()) {
    // Factories return the new object.
    result_ ^= result.raw();
  } else {
    ASSERT(!receiver->IsNull());
    result_ ^= (*receiver).raw();
  }
  if (I->obfuscate() &&
      (result_.clazz() == I->object_store()->symbol_class())) {
    Obfuscator::ObfuscateSymbolInstance(H.thread(), result_);
  }
  result_ = H.Canonicalize(result_);
}

void ConstantEvaluator::EvaluateNot() {
  result_ ^= Bool::Get(!EvaluateBooleanExpressionHere()).raw();
}

void ConstantEvaluator::EvaluateLogicalExpression() {
  bool left = EvaluateBooleanExpressionHere();  // read left.
  LogicalOperator op = static_cast<LogicalOperator>(helper_->ReadByte());
  if (op == kAnd) {
    if (left) {
      EvaluateBooleanExpressionHere();  // read right.
    } else {
      helper_->SkipExpression();  // read right.
    }
  } else {
    ASSERT(op == kOr);
    if (!left) {
      EvaluateBooleanExpressionHere();  // read right.
    } else {
      helper_->SkipExpression();  // read right.
    }
  }
}

void ConstantEvaluator::EvaluateAsExpression() {
  TokenPosition position = helper_->ReadPosition();
  const uint8_t flags = helper_->ReadFlags();
  const bool is_type_error = (flags & (1 << 0)) != 0;

  // Check that this AsExpression was inserted by the front-end.
  if (!is_type_error) {
    H.ReportError(
        script_, position,
        "explicit as operator is not permitted in constant expression");
  }

  EvaluateExpression(helper_->ReaderOffset(), false);

  const AbstractType& type = T.BuildType();
  if (!type.IsInstantiated()) {
    const String& type_str = String::Handle(type.UserVisibleName());
    H.ReportError(
        script_, position,
        "Not a constant expression: right hand side of an implicit "
        "as-expression is expected to be an instantiated type, got %s",
        type_str.ToCString());
  }

  const TypeArguments& instantiator_type_arguments = TypeArguments::Handle();
  const TypeArguments& function_type_arguments = TypeArguments::Handle();
  if (!result_.IsInstanceOf(type, instantiator_type_arguments,
                            function_type_arguments)) {
    const AbstractType& rtype =
        AbstractType::Handle(result_.GetType(Heap::kNew));
    const String& result_str = String::Handle(rtype.UserVisibleName());
    const String& type_str = String::Handle(type.UserVisibleName());
    H.ReportError(
        script_, position,
        "Not a constant expression: Type '%s' is not a subtype of type '%s'",
        result_str.ToCString(), type_str.ToCString());
  }
}

void ConstantEvaluator::EvaluateConditionalExpression() {
  bool condition = EvaluateBooleanExpressionHere();
  if (condition) {
    EvaluateExpression(helper_->ReaderOffset(), false);  // read then.
    helper_->SkipExpression();                           // read otherwise.
  } else {
    helper_->SkipExpression();                           // read then.
    EvaluateExpression(helper_->ReaderOffset(), false);  // read otherwise.
  }
  helper_->SkipOptionalDartType();  // read unused static type.
}

void ConstantEvaluator::EvaluateStringConcatenation() {
  TokenPosition position = helper_->ReadPosition();  // read position.
  intptr_t length = helper_->ReadListLength();       // read list length.

  bool all_string = true;
  const Array& strings =
      Array::Handle(Z, Array::New(length, H.allocation_space()));
  for (intptr_t i = 0; i < length; ++i) {
    EvaluateExpression(helper_->ReaderOffset(),
                       false);  // read ith expression.
    strings.SetAt(i, result_);
    all_string = all_string && result_.IsString();
  }
  if (all_string) {
    result_ = String::ConcatAll(strings, Heap::kOld);
    result_ = H.Canonicalize(result_);
  } else {
    // Get string interpolation function.
    const Class& cls =
        Class::Handle(Z, Library::LookupCoreClass(Symbols::StringBase()));
    ASSERT(!cls.IsNull());
    const Function& func = Function::Handle(
        Z, cls.LookupStaticFunction(
               Library::PrivateCoreLibName(Symbols::Interpolate())));
    ASSERT(!func.IsNull());

    // Build argument array to pass to the interpolation function.
    const Array& interpolate_arg = Array::Handle(Z, Array::New(1, Heap::kOld));
    interpolate_arg.SetAt(0, strings);

    // Run and canonicalize.
    const Object& result =
        RunFunction(position, func, interpolate_arg, Array::null_array());
    result_ = H.Canonicalize(String::Cast(result));
  }
}

void ConstantEvaluator::EvaluateSymbolLiteral() {
  const Class& owner = *active_class_->klass;
  const Library& lib = Library::Handle(Z, owner.library());
  String& symbol_value = H.DartIdentifier(lib, helper_->ReadStringReference());
  const Class& symbol_class =
      Class::ZoneHandle(Z, I->object_store()->symbol_class());
  ASSERT(!symbol_class.IsNull());
  const Function& symbol_constructor = Function::ZoneHandle(
      Z, symbol_class.LookupConstructor(Symbols::SymbolCtor()));
  ASSERT(!symbol_constructor.IsNull());
  result_ ^= EvaluateConstConstructorCall(
      symbol_class, TypeArguments::Handle(Z), symbol_constructor, symbol_value);
}

void ConstantEvaluator::EvaluateTypeLiteral() {
  const AbstractType& type = T.BuildType();
  result_ = type.raw();
}

void ConstantEvaluator::EvaluateListLiteralInternal() {
  helper_->ReadPosition();  // read position.
  const TypeArguments& type_arguments = T.BuildTypeArguments(1);  // read type.
  intptr_t length = helper_->ReadListLength();  // read list length.
  const Array& const_list =
      Array::ZoneHandle(Z, Array::New(length, Heap::kOld));
  const_list.SetTypeArguments(type_arguments);
  Instance& expression = Instance::Handle(Z);
  for (intptr_t i = 0; i < length; ++i) {
    expression = EvaluateExpression(helper_->ReaderOffset(),
                                    false);  // read ith expression.
    const_list.SetAt(i, expression);
  }
  const_list.MakeImmutable();
  result_ = H.Canonicalize(const_list);
}

void ConstantEvaluator::EvaluateMapLiteralInternal() {
  helper_->ReadPosition();  // read position.
  const TypeArguments& type_arguments =
      T.BuildTypeArguments(2);  // read key type and value type.

  intptr_t length = helper_->ReadListLength();  // read length of entries.

  // This MapLiteral wasn't cached, so content isn't cached either.
  Array& const_kv_array = Array::Handle(Z, Array::New(2 * length, Heap::kOld));
  Instance& temp = Instance::Handle(Z);
  for (intptr_t i = 0; i < length; ++i) {
    temp = EvaluateExpression(helper_->ReaderOffset(), false);  // read key.
    const_kv_array.SetAt(2 * i + 0, temp);
    temp = EvaluateExpression(helper_->ReaderOffset(), false);  // read value.
    const_kv_array.SetAt(2 * i + 1, temp);
  }

  const_kv_array.MakeImmutable();
  const_kv_array ^= H.Canonicalize(const_kv_array);

  const Class& map_class =
      Class::Handle(Z, Library::LookupCoreClass(Symbols::ImmutableMap()));
  ASSERT(!map_class.IsNull());
  ASSERT(map_class.NumTypeArguments() == 2);

  const Field& field =
      Field::Handle(Z, map_class.LookupInstanceFieldAllowPrivate(
                           H.DartSymbolObfuscate("_kvPairs")));
  ASSERT(!field.IsNull());

  // NOTE: This needs to be kept in sync with `runtime/lib/immutable_map.dart`!
  result_ = Instance::New(map_class, Heap::kOld);
  ASSERT(!result_.IsNull());
  result_.SetTypeArguments(type_arguments);
  result_.SetField(field, const_kv_array);
  result_ = H.Canonicalize(result_);
}

void ConstantEvaluator::EvaluateLet() {
  ASSERT(IsBuildingFlowGraph());
  intptr_t kernel_position =
      helper_->ReaderOffset() + helper_->data_program_offset_;

  LocalVariable* local = flow_graph_builder_->LookupVariable(kernel_position);

  // read variable declaration.
  VariableDeclarationHelper helper(helper_);
  helper.ReadUntilExcluding(VariableDeclarationHelper::kInitializer);
  Tag tag = helper_->ReadTag();  // read (first part of) initializer.
  if (tag == kNothing) {
    local->SetConstValue(Instance::ZoneHandle(Z, Instance::null()));
  } else {
    local->SetConstValue(Instance::ZoneHandle(
        Z, EvaluateExpression(helper_->ReaderOffset(),
                              false)));  // read rest of initializer.
  }

  EvaluateExpression(helper_->ReaderOffset(), false);  // read body
}

void ConstantEvaluator::EvaluatePartialTearoffInstantiation() {
  // This method call wasn't cached, so receiver et al. isn't cached either.
  const Instance& receiver = Instance::Handle(
      Z, EvaluateExpression(helper_->ReaderOffset(), false));  // read receiver.
  if (!receiver.IsClosure()) {
    H.ReportError(script_, TokenPosition::kNoSource, "Expected closure.");
  }
  const Closure& old_closure = Closure::Cast(receiver);

  // read type arguments.
  intptr_t num_type_args = helper_->ReadListLength();
  const TypeArguments* type_args = &T.BuildTypeArguments(num_type_args);
  if (!type_args->IsNull() && !type_args->IsInstantiated()) {
    H.ReportError(
        script_, TokenPosition::kNoSource,
        "Type arguments in partial instantiations must be instantiated and are "
        "therefore not allowed to depend on type parameters.");
  }

  // Create new closure with the type arguments inserted, and other things
  // copied over.
  Closure& new_closure = Closure::Handle(
      Z,
      Closure::New(
          TypeArguments::Handle(Z, old_closure.instantiator_type_arguments()),
          TypeArguments::Handle(old_closure.function_type_arguments()),
          *type_args, Function::Handle(Z, old_closure.function()),
          Context::Handle(Z, old_closure.context()), Heap::kOld));
  result_ = H.Canonicalize(new_closure);
}

void ConstantEvaluator::EvaluateBigIntLiteral() {
  const String& value =
      H.DartString(helper_->ReadStringReference());  // read string reference.
  result_ = Integer::New(value, Heap::kOld);
  if (result_.IsNull()) {
    H.ReportError(script_, TokenPosition::kNoSource,
                  "Integer literal %s is out of range", value.ToCString());
  }
  result_ = H.Canonicalize(result_);
}

void ConstantEvaluator::EvaluateStringLiteral() {
  result_ = H.DartSymbolPlain(helper_->ReadStringReference())
                .raw();  // read string reference.
}

void ConstantEvaluator::EvaluateIntLiteral(uint8_t payload) {
  int64_t value = static_cast<int32_t>(payload) - SpecializedIntLiteralBias;
  result_ = Integer::New(value, Heap::kOld);
  result_ = H.Canonicalize(result_);
}

void ConstantEvaluator::EvaluateIntLiteral(bool is_negative) {
  int64_t value = is_negative ? -static_cast<int64_t>(helper_->ReadUInt())
                              : helper_->ReadUInt();  // read value.
  result_ = Integer::New(value, Heap::kOld);
  result_ = H.Canonicalize(result_);
}

void ConstantEvaluator::EvaluateDoubleLiteral() {
  result_ = Double::New(helper_->ReadDouble(), Heap::kOld);  // read value.
  result_ = H.Canonicalize(result_);
}

void ConstantEvaluator::EvaluateBoolLiteral(bool value) {
  result_ = Bool::Get(value).raw();
}

void ConstantEvaluator::EvaluateNullLiteral() {
  result_ = Instance::null();
}

void ConstantEvaluator::EvaluateConstantExpression() {
  // Please note that this constants array is constructed exactly once, see
  // ReadConstantTable() and is immutable from that point on, so there is no
  // need to guard against concurrent access between mutator and background
  // compiler.
  KernelConstantsMap constant_map(H.constants().raw());
  result_ ^= constant_map.GetOrDie(helper_->ReadUInt());
  ASSERT(constant_map.Release().raw() == H.constants().raw());
}

// This depends on being about to read the list of positionals on arguments.
const Object& ConstantEvaluator::RunFunction(TokenPosition position,
                                             const Function& function,
                                             intptr_t argument_count,
                                             const Instance* receiver,
                                             const TypeArguments* type_args) {
  // We use a kernel2kernel constant evaluator in Dart 2.0 AOT compilation, so
  // we should never end up evaluating constants using the VM's constant
  // evaluator.
  if (FLAG_precompiled_mode) {
    UNREACHABLE();
  }

  // We do not support generic methods yet.
  ASSERT((receiver == NULL) || (type_args == NULL));
  intptr_t extra_arguments =
      (receiver != NULL ? 1 : 0) + (type_args != NULL ? 1 : 0);

  // Build up arguments.
  const Array& arguments = Array::Handle(
      Z, Array::New(extra_arguments + argument_count, H.allocation_space()));
  intptr_t pos = 0;
  if (receiver != NULL) {
    arguments.SetAt(pos++, *receiver);
  }
  if (type_args != NULL) {
    arguments.SetAt(pos++, *type_args);
  }

  // List of positional.
  intptr_t list_length = helper_->ReadListLength();  // read list length.
  for (intptr_t i = 0; i < list_length; ++i) {
    EvaluateExpression(helper_->ReaderOffset(),
                       false);  // read ith expression.
    arguments.SetAt(pos++, result_);
  }

  // List of named.
  list_length = helper_->ReadListLength();  // read list length.
  const Array& names =
      Array::Handle(Z, Array::New(list_length, H.allocation_space()));
  for (intptr_t i = 0; i < list_length; ++i) {
    String& name = H.DartSymbolObfuscate(
        helper_->ReadStringReference());  // read ith name index.
    names.SetAt(i, name);
    EvaluateExpression(helper_->ReaderOffset(),
                       false);  // read ith expression.
    arguments.SetAt(pos++, result_);
  }

  return RunFunction(position, function, arguments, names);
}

const Object& ConstantEvaluator::RunFunction(const TokenPosition position,
                                             const Function& function,
                                             const Array& arguments,
                                             const Array& names) {
  // We do not support generic methods yet.
  const int kTypeArgsLen = 0;
  const Array& args_descriptor = Array::Handle(
      Z, ArgumentsDescriptor::New(kTypeArgsLen, arguments.Length(), names));
  const Object& result = Object::Handle(
      Z, DartEntry::InvokeFunction(function, arguments, args_descriptor));
  if (result.IsError()) {
    H.ReportError(Error::Cast(result), script_, position,
                  "error evaluating constant constructor");
  }
  return result;
}

const Object& ConstantEvaluator::RunMethodCall(const TokenPosition position,
                                               const Function& function,
                                               const Instance* receiver) {
  intptr_t argument_count = helper_->ReadUInt();  // read arguments count.

  // TODO(28109) Support generic methods in the VM or reify them away.
  ASSERT(helper_->PeekListLength() == 0);
  helper_->SkipListOfDartTypes();  // read list of types.

  // Run the method.
  return RunFunction(position, function, argument_count, receiver, NULL);
}

RawObject* ConstantEvaluator::EvaluateConstConstructorCall(
    const Class& type_class,
    const TypeArguments& type_arguments,
    const Function& constructor,
    const Object& argument) {
  // We use a kernel2kernel constant evaluator in Dart 2.0 AOT compilation, so
  // we should never end up evaluating constants using the VM's constant
  // evaluator.
  if (FLAG_precompiled_mode) {
    UNREACHABLE();
  }

  // Factories have one extra argument: the type arguments.
  // Constructors have 1 extra arguments: receiver.
  const int kTypeArgsLen = 0;
  const int kNumArgs = 1;
  const int kNumExtraArgs = 1;
  const int argument_count = kNumArgs + kNumExtraArgs;
  const Array& arg_values =
      Array::Handle(Z, Array::New(argument_count, Heap::kOld));
  Instance& instance = Instance::Handle(Z);
  if (!constructor.IsFactory()) {
    instance = Instance::New(type_class, Heap::kOld);
    if (!type_arguments.IsNull()) {
      ASSERT(type_arguments.IsInstantiated());
      instance.SetTypeArguments(
          TypeArguments::Handle(Z, type_arguments.Canonicalize()));
    }
    arg_values.SetAt(0, instance);
  } else {
    // Prepend type_arguments to list of arguments to factory.
    ASSERT(type_arguments.IsZoneHandle());
    arg_values.SetAt(0, type_arguments);
  }
  arg_values.SetAt((0 + kNumExtraArgs), argument);
  const Array& args_descriptor =
      Array::Handle(Z, ArgumentsDescriptor::New(kTypeArgsLen, argument_count,
                                                Object::empty_array()));
  const Object& result = Object::Handle(
      Z, DartEntry::InvokeFunction(constructor, arg_values, args_descriptor));
  ASSERT(!result.IsError());
  if (constructor.IsFactory()) {
    // The factory method returns the allocated object.
    instance ^= result.raw();
  }
  if (I->obfuscate() &&
      (instance.clazz() == I->object_store()->symbol_class())) {
    Obfuscator::ObfuscateSymbolInstance(H.thread(), instance);
  }
  return H.Canonicalize(instance);
}

const TypeArguments* ConstantEvaluator::TranslateTypeArguments(
    const Function& target,
    Class* target_klass) {
  intptr_t type_count = helper_->ReadListLength();  // read type count.

  const TypeArguments* type_arguments = NULL;
  if (type_count > 0) {
    type_arguments = &T.BuildInstantiatedTypeArguments(
        *target_klass, type_count);  // read types.

    if (!(type_arguments->IsNull() || type_arguments->IsInstantiated())) {
      H.ReportError(script_, TokenPosition::kNoSource,
                    "Type must be constant in const constructor.");
    }
  } else if (target.IsFactory() && type_arguments == NULL) {
    // All factories take a type arguments vector as first argument (independent
    // of whether the class is generic or not).
    type_arguments = &TypeArguments::ZoneHandle(Z, TypeArguments::null());
  }
  return type_arguments;
}

bool ConstantEvaluator::EvaluateBooleanExpressionHere() {
  EvaluateExpression(helper_->ReaderOffset(), false);
  AssertBool();
  return result_.raw() == Bool::True().raw();
}

bool ConstantEvaluator::GetCachedConstant(intptr_t kernel_offset,
                                          Instance* value) {
  if (!IsBuildingFlowGraph()) return false;

  const Function& function = flow_graph_builder_->parsed_function_->function();
  if (function.kind() == RawFunction::kImplicitStaticFinalGetter) {
    // Don't cache constants in initializer expressions. They get
    // evaluated only once.
    return false;
  }

  bool is_present = false;
  ASSERT(!script_.InVMIsolateHeap());
  if (script_.compile_time_constants() == Array::null()) {
    return false;
  }
  {
    // Any access to constants arrays must be locked since mutator and
    // background compiler can access the array at the same time.
    SafepointMutexLocker ml(H.thread()->isolate()->kernel_constants_mutex());

    KernelConstantsMap constants(script_.compile_time_constants());
    *value ^= constants.GetOrNull(kernel_offset + helper_->data_program_offset_,
                                  &is_present);
    constants.Release();
  }
  return is_present;
}

void ConstantEvaluator::CacheConstantValue(intptr_t kernel_offset,
                                           const Instance& value) {
  ASSERT(Thread::Current()->IsMutatorThread());

  if (!IsBuildingFlowGraph()) return;

  const Function& function = flow_graph_builder_->parsed_function_->function();
  if (function.kind() == RawFunction::kImplicitStaticFinalGetter) {
    // Don't cache constants in initializer expressions. They get
    // evaluated only once.
    return;
  }
  const intptr_t kInitialConstMapSize = 16;
  ASSERT(!script_.InVMIsolateHeap());
  if (script_.compile_time_constants() == Array::null()) {
    const Array& array = Array::Handle(
        HashTables::New<KernelConstantsMap>(kInitialConstMapSize, Heap::kNew));
    script_.set_compile_time_constants(array);
  }
  {
    // Any access to constants arrays must be locked since mutator and
    // background compiler can access the array at the same time.
    SafepointMutexLocker ml(H.thread()->isolate()->kernel_constants_mutex());

    KernelConstantsMap constants(script_.compile_time_constants());
    constants.InsertNewOrGetValue(kernel_offset + helper_->data_program_offset_,
                                  value);
    script_.set_compile_time_constants(constants.Release());
  }
}

ConstantHelper::ConstantHelper(Zone* zone,
                               KernelReaderHelper* helper,
                               TypeTranslator* type_translator,
                               ActiveClass* active_class,
                               NameIndex skip_vmservice_library)
    : zone_(zone),
      helper_(*helper),
      type_translator_(*type_translator),
      active_class_(active_class),
      const_evaluator_(helper, type_translator, active_class, nullptr),
      translation_helper_(helper->translation_helper_),
      skip_vmservice_library_(skip_vmservice_library),
      symbol_class_(Class::Handle(zone)),
      symbol_name_field_(Field::Handle(zone)),
      temp_type_(AbstractType::Handle(zone)),
      temp_type_arguments_(TypeArguments::Handle(zone)),
      temp_type_arguments2_(TypeArguments::Handle(zone)),
      temp_type_arguments3_(TypeArguments::Handle(zone)),
      temp_object_(Object::Handle(zone)),
      temp_string_(String::Handle(zone)),
      temp_array_(Array::Handle(zone)),
      temp_instance_(Instance::Handle(zone)),
      temp_field_(Field::Handle(zone)),
      temp_class_(Class::Handle(zone)),
      temp_library_(Library::Handle(zone)),
      temp_function_(Function::Handle(zone)),
      temp_closure_(Closure::Handle(zone)),
      temp_context_(Context::Handle(zone)),
      temp_integer_(Integer::Handle(zone)) {
  temp_library_ = Library::InternalLibrary();
  ASSERT(!temp_library_.IsNull());

  symbol_class_ = temp_library_.LookupClass(Symbols::Symbol());
  ASSERT(!symbol_class_.IsNull());

  symbol_name_field_ =
      symbol_class_.LookupInstanceFieldAllowPrivate(Symbols::_name());
  ASSERT(!symbol_name_field_.IsNull());
}

const Array& ConstantHelper::ReadConstantTable() {
  const intptr_t number_of_constants = helper_.ReadUInt();
  if (number_of_constants == 0) {
    return Array::empty_array();
  }

  const Library& corelib = Library::Handle(Z, Library::CoreLibrary());
  const Class& list_class =
      Class::Handle(Z, corelib.LookupClassAllowPrivate(Symbols::_List()));

  // Eagerly finalize _ImmutableList (instead of doing it on every list
  // constant).
  temp_class_ = I->class_table()->At(kImmutableArrayCid);
  temp_object_ = temp_class_.EnsureIsFinalized(H.thread());
  ASSERT(temp_object_.IsNull());

  KernelConstantsMap constants(
      HashTables::New<KernelConstantsMap>(number_of_constants, Heap::kOld));

  const intptr_t start_offset = helper_.ReaderOffset();

  for (intptr_t i = 0; i < number_of_constants; ++i) {
    const intptr_t offset = helper_.ReaderOffset();
    const intptr_t constant_tag = helper_.ReadByte();
    switch (constant_tag) {
      case kNullConstant:
        temp_instance_ = Instance::null();
        break;
      case kBoolConstant:
        temp_instance_ = helper_.ReadByte() == 1 ? Object::bool_true().raw()
                                                 : Object::bool_false().raw();
        break;
      case kIntConstant: {
        temp_instance_ = const_evaluator_.EvaluateExpression(
            helper_.ReaderOffset(), false /* reset position */);
        break;
      }
      case kDoubleConstant: {
        temp_instance_ = Double::New(helper_.ReadDouble(), Heap::kOld);
        temp_instance_ = H.Canonicalize(temp_instance_);
        break;
      }
      case kStringConstant: {
        temp_instance_ =
            H.Canonicalize(H.DartString(helper_.ReadStringReference()));
        break;
      }
      case kSymbolConstant: {
        const NameIndex index = helper_.ReadCanonicalNameReference();
        if (index == -1) {
          temp_library_ = Library::null();
        } else {
          temp_library_ = H.LookupLibraryByKernelLibrary(index);
        }
        const String& symbol =
            H.DartIdentifier(temp_library_, helper_.ReadStringReference());
        temp_instance_ = Instance::New(symbol_class_, Heap::kOld);
        temp_instance_.SetField(symbol_name_field_, symbol);
        temp_instance_ = H.Canonicalize(temp_instance_);
        break;
      }
      case kListConstant: {
        temp_type_arguments_ = TypeArguments::New(1, Heap::kOld);
        const AbstractType& type = type_translator_.BuildType();
        temp_type_arguments_.SetTypeAt(0, type);
        InstantiateTypeArguments(list_class, &temp_type_arguments_);

        const intptr_t length = helper_.ReadUInt();
        temp_array_ = ImmutableArray::New(length, Heap::kOld);
        temp_array_.SetTypeArguments(temp_type_arguments_);
        for (intptr_t j = 0; j < length; ++j) {
          const intptr_t entry_offset = helper_.ReadUInt();
          ASSERT(entry_offset < (offset - start_offset));  // We have a DAG!
          temp_object_ = constants.GetOrDie(entry_offset);
          temp_array_.SetAt(j, temp_object_);
        }

        temp_instance_ = H.Canonicalize(temp_array_);
        break;
      }
      case kSetConstant:
        // Set literals are currently desugared in the frontend and will not
        // reach the VM. See http://dartbug.com/35124 for discussion.
        UNREACHABLE();
        break;
      case kInstanceConstant: {
        const NameIndex index = helper_.ReadCanonicalNameReference();
        if (ShouldSkipConstant(index)) {
          temp_instance_ = Instance::null();
          break;
        }

        temp_class_ = H.LookupClassByKernelClass(index);
        temp_object_ = temp_class_.EnsureIsFinalized(H.thread());
        ASSERT(temp_object_.IsNull());

        temp_instance_ = Instance::New(temp_class_, Heap::kOld);

        const intptr_t number_of_type_arguments = helper_.ReadUInt();
        if (temp_class_.NumTypeArguments() > 0) {
          temp_type_arguments_ =
              TypeArguments::New(number_of_type_arguments, Heap::kOld);
          for (intptr_t j = 0; j < number_of_type_arguments; ++j) {
            temp_type_arguments_.SetTypeAt(j, type_translator_.BuildType());
          }
          InstantiateTypeArguments(temp_class_, &temp_type_arguments_);
          temp_instance_.SetTypeArguments(temp_type_arguments_);
        } else {
          ASSERT(number_of_type_arguments == 0);
        }

        const intptr_t number_of_fields = helper_.ReadUInt();
        for (intptr_t j = 0; j < number_of_fields; ++j) {
          temp_field_ =
              H.LookupFieldByKernelField(helper_.ReadCanonicalNameReference());
          const intptr_t entry_offset = helper_.ReadUInt();
          ASSERT(entry_offset < (offset - start_offset));  // We have a DAG!
          temp_object_ = constants.GetOrDie(entry_offset);
          temp_instance_.SetField(temp_field_, temp_object_);
        }

        temp_instance_ = H.Canonicalize(temp_instance_);
        break;
      }
      case kPartialInstantiationConstant: {
        const intptr_t entry_offset = helper_.ReadUInt();
        ASSERT(entry_offset < (offset - start_offset));  // We have a DAG!
        temp_object_ = constants.GetOrDie(entry_offset);

        // Happens if the tearoff was in the vmservice library and we have
        // [skip_vm_service_library] enabled.
        if (temp_object_.IsNull()) {
          temp_instance_ = Instance::null();
          break;
        }

        const intptr_t number_of_type_arguments = helper_.ReadUInt();
        ASSERT(number_of_type_arguments > 0);
        temp_type_arguments_ =
            TypeArguments::New(number_of_type_arguments, Heap::kOld);
        for (intptr_t j = 0; j < number_of_type_arguments; ++j) {
          temp_type_arguments_.SetTypeAt(j, type_translator_.BuildType());
        }

        // Make a copy of the old closure, with the delayed type arguments
        // set to [temp_type_arguments_].
        temp_closure_ = Closure::RawCast(temp_object_.raw());
        temp_function_ = temp_closure_.function();
        temp_type_arguments2_ = temp_closure_.instantiator_type_arguments();
        temp_type_arguments3_ = temp_closure_.function_type_arguments();
        temp_context_ = temp_closure_.context();
        temp_closure_ = Closure::New(
            temp_type_arguments2_, Object::null_type_arguments(),
            temp_type_arguments_, temp_function_, temp_context_, Heap::kOld);
        temp_instance_ = H.Canonicalize(temp_closure_);
        break;
      }
      case kTearOffConstant: {
        const NameIndex index = helper_.ReadCanonicalNameReference();
        if (ShouldSkipConstant(index)) {
          temp_instance_ = Instance::null();
          break;
        }

        temp_function_ = H.LookupStaticMethodByKernelProcedure(index);
        temp_function_ = temp_function_.ImplicitClosureFunction();
        temp_instance_ = temp_function_.ImplicitStaticClosure();
        temp_instance_ = H.Canonicalize(temp_instance_);
        break;
      }
      case kTypeLiteralConstant: {
        temp_instance_ = type_translator_.BuildType().raw();
        break;
      }
      case kMapConstant:
        // Note: This is already lowered to InstanceConstant/ListConstant.
        UNREACHABLE();
        break;
      case kUnevaluatedConstant:
        // We should not see unevaluated constants in the constant table, they
        // should have been fully evaluated before we get them.
        UNREACHABLE();
        break;
      default:
        UNREACHABLE();
    }
    constants.InsertNewOrGetValue(offset - start_offset, temp_instance_);
  }
  return Array::Handle(Z, constants.Release().raw());
}

void ConstantHelper::InstantiateTypeArguments(const Class& receiver_class,
                                              TypeArguments* type_arguments) {
  // We make a temporary [Type] object and use `ClassFinalizer::FinalizeType` to
  // finalize the argument types.
  // (This can for example make the [type_arguments] vector larger)
  temp_type_ =
      Type::New(receiver_class, *type_arguments, TokenPosition::kNoSource);
  temp_type_ = ClassFinalizer::FinalizeType(*active_class_->klass, temp_type_,
                                            ClassFinalizer::kCanonicalize);
  *type_arguments = temp_type_.arguments();
}

// If [index] has `dart:vm_service` as a parent and we are skipping the VM
// service library, this method returns `true`, otherwise `false`.
bool ConstantHelper::ShouldSkipConstant(NameIndex index) {
  if (index == NameIndex::kInvalidName) {
    return false;
  }
  while (!H.IsLibrary(index)) {
    index = H.CanonicalNameParent(index);
  }
  ASSERT(H.IsLibrary(index));
  return index == skip_vmservice_library_;
}

}  // namespace kernel
}  // namespace dart

#endif  // !defined(DART_PRECOMPILED_RUNTIME)
