// 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_reader.h"

#include "vm/object_store.h"

namespace dart {
namespace kernel {

#define Z (zone_)
#define H (translation_helper_)

// Note: If changing how the constants are saved in the binary (and thus how
// they are read here) be aware that there's also some reading going on in
// KernelLoader::ReadVMAnnotations which then also has to be updated!

ConstantReader::ConstantReader(KernelReaderHelper* helper,
                               ActiveClass* active_class)
    : helper_(helper),
      zone_(helper->zone_),
      translation_helper_(helper->translation_helper_),
      active_class_(active_class),
      script_(helper->script()),
      result_(Object::Handle(zone_)) {}

InstancePtr ConstantReader::ReadConstantInitializer() {
  Tag tag = helper_->ReadTag();  // read tag.
  switch (tag) {
    case kSomething:
      return ReadConstantExpression();
    default:
      H.ReportError(script_, TokenPosition::kNoSource,
                    "Not a constant expression: unexpected kernel tag %s (%d)",
                    Reader::TagName(tag), tag);
  }
  return Instance::RawCast(result_.ptr());
}

InstancePtr ConstantReader::ReadConstantExpression() {
  Tag tag = helper_->ReadTag();  // read tag.
  switch (tag) {
    case kConstantExpression:
      helper_->ReadPosition();
      helper_->SkipDartType();
      result_ = ReadConstant(helper_->ReadUInt());
      break;
    case kInvalidExpression: {
      helper_->ReadPosition();  // Skip position.
      const String& message = H.DartString(helper_->ReadStringReference());
      // Invalid expression message has pointer to the source code, no need to
      // report it twice.
      H.ReportError(helper_->script(), TokenPosition::kNoSource, "%s",
                    message.ToCString());
      break;
    }
    default:
      H.ReportError(script_, TokenPosition::kNoSource,
                    "Not a constant expression: unexpected kernel tag %s (%d)",
                    Reader::TagName(tag), tag);
  }
  return Instance::RawCast(result_.ptr());
}

ObjectPtr ConstantReader::ReadAnnotations() {
  intptr_t list_length = helper_->ReadListLength();  // read list length.
  const auto& metadata_values =
      Array::Handle(Z, ImmutableArray::New(list_length, H.allocation_space()));
  Instance& value = Instance::Handle(Z);
  for (intptr_t i = 0; i < list_length; ++i) {
    // This will read the expression.
    value = ReadConstantExpression();
    metadata_values.SetAt(i, value);
  }
  return H.Canonicalize(metadata_values);
}

InstancePtr ConstantReader::ReadConstant(intptr_t constant_index) {
  ASSERT(!H.constants().IsNull());
  ASSERT(!H.constants_table().IsNull());  // raw bytes

  // For kernel-level cache (in contrast with script-level caching),
  // we need to access the raw constants array inside the shared
  // KernelProgramInfo directly, so that all scripts will see the
  // results after new insertions. These accesses at kernel-level
  // must be locked since mutator and background compiler can
  // access the array at the same time.
  {
    SafepointMutexLocker ml(
        H.thread()->isolate_group()->kernel_constants_mutex());
    const auto& constants_array = Array::Handle(Z, H.info().constants());
    ASSERT(constant_index < constants_array.Length());
    result_ = constants_array.At(constant_index);
  }

  // On miss, evaluate, and insert value.
  if (result_.ptr() == Object::sentinel().ptr()) {
    LeaveCompilerScope cs(H.thread());
    result_ = ReadConstantInternal(constant_index);
    SafepointMutexLocker ml(
        H.thread()->isolate_group()->kernel_constants_mutex());
    const auto& constants_array = Array::Handle(Z, H.info().constants());
    ASSERT(constant_index < constants_array.Length());
    constants_array.SetAt(constant_index, result_);
  }
  return Instance::RawCast(result_.ptr());
}

bool ConstantReader::IsInstanceConstant(intptr_t constant_index,
                                        const Class& clazz) {
  // Get reader directly into raw bytes of constant table/constant mapping.
  KernelReaderHelper reader(Z, &H, script_, H.constants_table(), 0);
  NavigateToIndex(&reader, constant_index);

  // Peek for an instance of the given clazz.
  if (reader.ReadByte() == kInstanceConstant) {
    const NameIndex index = reader.ReadCanonicalNameReference();
    return H.LookupClassByKernelClass(index) == clazz.ptr();
  }
  return false;
}

intptr_t ConstantReader::NumConstants() {
  ASSERT(!H.constants_table().IsNull());
  KernelReaderHelper reader(Z, &H, script_, H.constants_table(), 0);
  return NumConstants(&reader);
}

intptr_t ConstantReader::NumConstants(KernelReaderHelper* reader) {
  // Get reader directly into raw bytes of constant table/constant mapping.
  // Get the length of the constants (at the end of the mapping).
  reader->SetOffset(reader->ReaderSize() - 4);
  return reader->ReadUInt32();
}

intptr_t ConstantReader::NavigateToIndex(KernelReaderHelper* reader,
                                         intptr_t constant_index) {
  const intptr_t num_constants = NumConstants(reader);

  // Get the binary offset of the constant at the wanted index.
  reader->SetOffset(reader->ReaderSize() - 4 - (num_constants * 4) +
                    (constant_index * 4));
  const intptr_t constant_offset = reader->ReadUInt32();

  reader->SetOffset(constant_offset);

  return constant_offset;
}

InstancePtr ConstantReader::ReadConstantInternal(intptr_t constant_index) {
  // Get reader directly into raw bytes of constant table/constant mapping.
  bool null_safety = H.thread()->isolate_group()->null_safety();
  KernelReaderHelper reader(Z, &H, script_, H.constants_table(), 0);
  const intptr_t constant_offset = NavigateToIndex(&reader, constant_index);

  // No function types returned as part of any types built should reference
  // free parent type args, ensured by clearing the enclosing function type.
  ActiveEnclosingFunctionScope scope(active_class_, nullptr);
  // Construct constant from raw bytes.
  Instance& instance = Instance::Handle(Z);
  const intptr_t constant_tag = reader.ReadByte();
  switch (constant_tag) {
    case kNullConstant:
      instance = Instance::null();
      break;
    case kBoolConstant:
      instance = reader.ReadByte() == 1 ? Object::bool_true().ptr()
                                        : Object::bool_false().ptr();
      break;
    case kIntConstant: {
      uint8_t payload = 0;
      Tag integer_tag = reader.ReadTag(&payload);  // read tag.
      switch (integer_tag) {
        case kBigIntLiteral: {
          const String& value = H.DartString(reader.ReadStringReference());
          instance = Integer::New(value, Heap::kOld);
          break;
        }
        case kSpecializedIntLiteral: {
          const int64_t value =
              static_cast<int32_t>(payload) - SpecializedIntLiteralBias;
          instance = Integer::New(value, Heap::kOld);
          break;
        }
        case kNegativeIntLiteral: {
          const int64_t value = -static_cast<int64_t>(reader.ReadUInt());
          instance = Integer::New(value, Heap::kOld);
          break;
        }
        case kPositiveIntLiteral: {
          const int64_t value = reader.ReadUInt();
          instance = Integer::New(value, Heap::kOld);
          break;
        }
        default:
          H.ReportError(
              script_, TokenPosition::kNoSource,
              "Cannot lazily read integer: unexpected kernel tag %s (%d)",
              Reader::TagName(integer_tag), integer_tag);
      }
      break;
    }
    case kDoubleConstant:
      instance = Double::New(reader.ReadDouble(), Heap::kOld);
      break;
    case kStringConstant:
      instance = H.DartSymbolPlain(reader.ReadStringReference()).ptr();
      break;
    case kSymbolConstant: {
      Library& library = Library::Handle(Z);
      library = Library::InternalLibrary();
      const auto& symbol_class =
          Class::Handle(Z, library.LookupClass(Symbols::Symbol()));
      const auto& symbol_name_field = Field::Handle(
          Z, symbol_class.LookupInstanceFieldAllowPrivate(Symbols::_name()));
      ASSERT(!symbol_name_field.IsNull());
      const NameIndex index = reader.ReadCanonicalNameReference();
      if (index == -1) {
        library = Library::null();
      } else {
        library = H.LookupLibraryByKernelLibrary(index);
      }
      const String& symbol =
          H.DartIdentifier(library, reader.ReadStringReference());
      instance = Instance::New(symbol_class, Heap::kOld);
      instance.SetField(symbol_name_field, symbol);
      break;
    }
    case kListConstant: {
      const auto& list_class = Class::Handle(
          Z, H.isolate_group()->object_store()->immutable_array_class());
      ASSERT(!list_class.IsNull());
      // Build type from the raw bytes (needs temporary translator).
      TypeTranslator type_translator(
          &reader, this, active_class_, /* finalize = */ true,
          active_class_->RequireConstCanonicalTypeErasure(null_safety),
          /* in_constant_context = */ true);
      auto& type_arguments =
          TypeArguments::Handle(Z, TypeArguments::New(1, Heap::kOld));
      AbstractType& type = type_translator.BuildType();
      type_arguments.SetTypeAt(0, type);
      // Instantiate class.
      type = Type::New(list_class, type_arguments);
      type = ClassFinalizer::FinalizeType(type, ClassFinalizer::kCanonicalize);
      type_arguments = type.arguments();
      // Fill array with constant elements.
      const intptr_t length = reader.ReadUInt();
      const Array& array =
          Array::Handle(Z, ImmutableArray::New(length, Heap::kOld));
      array.SetTypeArguments(type_arguments);
      Instance& constant = Instance::Handle(Z);
      for (intptr_t j = 0; j < length; ++j) {
        // Recurse into lazily evaluating all "sub" constants
        // needed to evaluate the current constant.
        const intptr_t entry_index = reader.ReadUInt();
        ASSERT(entry_index < constant_offset);  // DAG!
        constant = ReadConstant(entry_index);
        array.SetAt(j, constant);
      }
      instance = array.ptr();
      break;
    }
    case kMapConstant: {
      const auto& map_class = Class::Handle(
          Z,
          H.isolate_group()->object_store()->immutable_linked_hash_map_class());
      ASSERT(!map_class.IsNull());

      // Build types from the raw bytes (needs temporary translator).
      TypeTranslator type_translator(
          &reader, this, active_class_, /* finalize = */ true,
          active_class_->RequireConstCanonicalTypeErasure(null_safety),
          /* in_constant_context = */ true);
      auto& type_arguments =
          TypeArguments::Handle(Z, TypeArguments::New(2, Heap::kOld));
      AbstractType& type = type_translator.BuildType();
      type_arguments.SetTypeAt(0, type);
      type = type_translator.BuildType().ptr();
      type_arguments.SetTypeAt(1, type);

      // Instantiate class.
      type = Type::New(map_class, type_arguments);
      type = ClassFinalizer::FinalizeType(type, ClassFinalizer::kCanonicalize);
      type_arguments = type.arguments();

      // Fill map with constant elements.
      const auto& map = LinkedHashMap::Handle(
          Z, ImmutableLinkedHashMap::NewUninitialized(Heap::kOld));
      ASSERT_EQUAL(map.GetClassId(), kImmutableLinkedHashMapCid);
      map.SetTypeArguments(type_arguments);
      const intptr_t length = reader.ReadUInt();
      const intptr_t used_data = (length << 1);
      map.set_used_data(used_data);

      const intptr_t data_size = Utils::RoundUpToPowerOfTwo(used_data);
      const auto& data = Array::Handle(Z, Array::New(data_size));
      map.set_data(data);

      map.set_deleted_keys(0);
      map.ComputeAndSetHashMask();

      Instance& constant = Instance::Handle(Z);
      for (intptr_t j = 0; j < used_data; ++j) {
        // Recurse into lazily evaluating all "sub" constants
        // needed to evaluate the current constant.
        const intptr_t entry_index = reader.ReadUInt();
        ASSERT(entry_index < constant_offset);  // DAG!
        constant = ReadConstant(entry_index);
        data.SetAt(j, constant);
      }

      instance = map.ptr();
      break;
    }
    case kSetConstant: {
      const auto& set_class = Class::Handle(
          Z,
          H.isolate_group()->object_store()->immutable_linked_hash_set_class());
      ASSERT(!set_class.IsNull());

      // Build types from the raw bytes (needs temporary translator).
      TypeTranslator type_translator(
          &reader, this, active_class_, /* finalize = */ true,
          active_class_->RequireConstCanonicalTypeErasure(null_safety),
          /* in_constant_context = */ true);
      auto& type_arguments =
          TypeArguments::Handle(Z, TypeArguments::New(1, Heap::kOld));
      AbstractType& type = type_translator.BuildType();
      type_arguments.SetTypeAt(0, type);

      // Instantiate class.
      type = Type::New(set_class, type_arguments);
      type = ClassFinalizer::FinalizeType(type, ClassFinalizer::kCanonicalize);
      type_arguments = type.arguments();

      // Fill set with constant elements.
      const auto& set = LinkedHashSet::Handle(
          Z, ImmutableLinkedHashSet::NewUninitialized(Heap::kOld));
      ASSERT_EQUAL(set.GetClassId(), kImmutableLinkedHashSetCid);
      set.SetTypeArguments(type_arguments);
      const intptr_t length = reader.ReadUInt();
      const intptr_t used_data = length;
      set.set_used_data(used_data);

      const intptr_t data_size = Utils::RoundUpToPowerOfTwo(used_data);
      const auto& data = Array::Handle(Z, Array::New(data_size));
      set.set_data(data);

      set.set_deleted_keys(0);
      set.ComputeAndSetHashMask();

      Instance& constant = Instance::Handle(Z);
      for (intptr_t j = 0; j < used_data; ++j) {
        // Recurse into lazily evaluating all "sub" constants
        // needed to evaluate the current constant.
        const intptr_t entry_index = reader.ReadUInt();
        ASSERT(entry_index < constant_offset);  // DAG!
        constant = ReadConstant(entry_index);
        data.SetAt(j, constant);
      }

      instance = set.ptr();
      break;
    }
    case kInstanceConstant: {
      const NameIndex index = reader.ReadCanonicalNameReference();
      const auto& klass = Class::Handle(Z, H.LookupClassByKernelClass(index));
      if (!klass.is_declaration_loaded()) {
        FATAL1(
            "Trying to evaluate an instance constant whose references class "
            "%s is not loaded yet.",
            klass.ToCString());
      }
      const auto& obj =
          Object::Handle(Z, klass.EnsureIsAllocateFinalized(H.thread()));
      ASSERT(obj.IsNull());
      ASSERT(klass.is_enum_class() || klass.is_const());
      instance = Instance::New(klass, Heap::kOld);
      // Build type from the raw bytes (needs temporary translator).
      TypeTranslator type_translator(
          &reader, this, active_class_, /* finalize = */ true,
          active_class_->RequireConstCanonicalTypeErasure(null_safety),
          /* in_constant_context = */ true);
      const intptr_t number_of_type_arguments = reader.ReadUInt();
      if (klass.NumTypeArguments() > 0) {
        auto& type_arguments = TypeArguments::Handle(
            Z, TypeArguments::New(number_of_type_arguments, Heap::kOld));
        for (intptr_t j = 0; j < number_of_type_arguments; ++j) {
          type_arguments.SetTypeAt(j, type_translator.BuildType());
        }
        // Instantiate class.
        auto& type = AbstractType::Handle(Z, Type::New(klass, type_arguments));
        type =
            ClassFinalizer::FinalizeType(type, ClassFinalizer::kCanonicalize);
        type_arguments = type.arguments();
        instance.SetTypeArguments(type_arguments);
      } else {
        ASSERT(number_of_type_arguments == 0);
      }
      // Set the fields.
      const intptr_t number_of_fields = reader.ReadUInt();
      Field& field = Field::Handle(Z);
      Instance& constant = Instance::Handle(Z);
      for (intptr_t j = 0; j < number_of_fields; ++j) {
        field = H.LookupFieldByKernelField(reader.ReadCanonicalNameReference());
        // Recurse into lazily evaluating all "sub" constants
        // needed to evaluate the current constant.
        const intptr_t entry_index = reader.ReadUInt();
        ASSERT(entry_index < constant_offset);  // DAG!
        constant = ReadConstant(entry_index);
        instance.SetField(field, constant);
      }
      break;
    }
    case kInstantiationConstant: {
      // Recurse into lazily evaluating the "sub" constant
      // needed to evaluate the current constant.
      const intptr_t entry_index = reader.ReadUInt();
      ASSERT(entry_index < constant_offset);  // DAG!
      const auto& constant = Instance::Handle(Z, ReadConstant(entry_index));
      ASSERT(!constant.IsNull());

      // Build type from the raw bytes (needs temporary translator).
      TypeTranslator type_translator(
          &reader, this, active_class_, /* finalize = */ true,
          active_class_->RequireConstCanonicalTypeErasure(null_safety),
          /* in_constant_context = */ true);
      const intptr_t number_of_type_arguments = reader.ReadUInt();
      ASSERT(number_of_type_arguments > 0);
      auto& type_arguments = TypeArguments::Handle(
          Z, TypeArguments::New(number_of_type_arguments, Heap::kOld));
      for (intptr_t j = 0; j < number_of_type_arguments; ++j) {
        type_arguments.SetTypeAt(j, type_translator.BuildType());
      }
      type_arguments = type_arguments.Canonicalize(Thread::Current(), nullptr);
      // Make a copy of the old closure, and set delayed type arguments.
      Closure& closure = Closure::Handle(Z, Closure::RawCast(constant.ptr()));
      Function& function = Function::Handle(Z, closure.function());
      const auto& type_arguments2 =
          TypeArguments::Handle(Z, closure.instantiator_type_arguments());
      // The function type arguments are used for type parameters from enclosing
      // closures. Though inner closures cannot be constants. We should
      // therefore see `null here.
      ASSERT(closure.function_type_arguments() == TypeArguments::null());
      Context& context = Context::Handle(Z, closure.context());
      instance = Closure::New(type_arguments2, Object::null_type_arguments(),
                              type_arguments, function, context, Heap::kOld);
      break;
    }
    case kStaticTearOffConstant:
    case kConstructorTearOffConstant:
    case kRedirectingFactoryTearOffConstant: {
      const NameIndex index = reader.ReadCanonicalNameReference();
      Function& function = Function::Handle(Z);
      if (H.IsConstructor(index)) {
        function = H.LookupConstructorByKernelConstructor(index);
      } else {
        function = H.LookupStaticMethodByKernelProcedure(index);
      }
      function = function.ImplicitClosureFunction();
      instance = function.ImplicitStaticClosure();
      break;
    }
    case kTypeLiteralConstant: {
      // Build type from the raw bytes (needs temporary translator).
      // Const canonical type erasure is not applied to constant type literals.
      // However, CFE must ensure that constant type literals can be
      // canonicalized to an identical representant independently of the null
      // safety mode currently in use (sound or unsound) or migration state of
      // the declaring library (legacy or opted-in).
      TypeTranslator type_translator(&reader, this, active_class_,
                                     /* finalize = */ true,
                                     /* apply_canonical_type_erasure = */ false,
                                     /* in_constant_context = */ true);
      instance = type_translator.BuildType().ptr();
      break;
    }
    default:
      // We should never see unevaluated constants (kUnevaluatedConstant) in
      // the constant table, they should have been fully evaluated before we
      // get them.
      H.ReportError(script_, TokenPosition::kNoSource,
                    "Cannot lazily read constant: unexpected kernel tag (%" Pd
                    ")",
                    constant_tag);
  }
  return H.Canonicalize(instance);
}

}  // namespace kernel
}  // namespace dart
