// 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"

namespace dart {
namespace kernel {

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

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_(Instance::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 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 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_offset) {
  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());
    KernelConstantsMap constant_map(H.info().constants());
    result_ ^= constant_map.GetOrNull(constant_offset);
    ASSERT(constant_map.Release().ptr() == H.info().constants());
  }

  // On miss, evaluate, and insert value.
  if (result_.IsNull()) {
    LeaveCompilerScope cs(H.thread());
    result_ = ReadConstantInternal(constant_offset);
    SafepointMutexLocker ml(
        H.thread()->isolate_group()->kernel_constants_mutex());
    KernelConstantsMap constant_map(H.info().constants());
    auto insert = constant_map.InsertNewOrGetValue(constant_offset, result_);
    ASSERT(insert == result_.ptr());
    H.info().set_constants(constant_map.Release());  // update!
  }
  return result_.ptr();
}

bool ConstantReader::IsInstanceConstant(intptr_t constant_offset,
                                        const Class& clazz) {
  // Get reader directly into raw bytes of constant table.
  KernelReaderHelper reader(Z, &H, script_, H.constants_table(), 0);
  reader.ReadUInt();  // skip variable-sized int for adjusted constant offset
  reader.SetOffset(reader.ReaderOffset() + constant_offset);
  // 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;
}

InstancePtr ConstantReader::ReadConstantInternal(intptr_t constant_offset) {
  // Get reader directly into raw bytes of constant table.
  bool null_safety = H.thread()->isolate_group()->null_safety();
  KernelReaderHelper reader(Z, &H, script_, H.constants_table(), 0);
  reader.ReadUInt();  // skip variable-sized int for adjusted constant offset
  reader.SetOffset(reader.ReaderOffset() + constant_offset);
  // 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& corelib = Library::Handle(Z, Library::CoreLibrary());
      const auto& list_class =
          Class::Handle(Z, corelib.LookupClassAllowPrivate(Symbols::_List()));
      // Build type from the raw bytes (needs temporary translator).
      TypeTranslator type_translator(
          &reader, this, active_class_, true,
          active_class_->RequireConstCanonicalTypeErasure(null_safety));
      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_offset = reader.ReadUInt();
        ASSERT(entry_offset < constant_offset);  // DAG!
        constant = ReadConstant(entry_offset);
        array.SetAt(j, constant);
      }
      instance = array.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_, true,
          active_class_->RequireConstCanonicalTypeErasure(null_safety));
      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.LookupFieldByKernelGetterOrSetter(
            reader.ReadCanonicalNameReference());
        // Recurse into lazily evaluating all "sub" constants
        // needed to evaluate the current constant.
        const intptr_t entry_offset = reader.ReadUInt();
        ASSERT(entry_offset < constant_offset);  // DAG!
        constant = ReadConstant(entry_offset);
        instance.SetField(field, constant);
      }
      break;
    }
    case kPartialInstantiationConstant: {
      // Recurse into lazily evaluating the "sub" constant
      // needed to evaluate the current constant.
      const intptr_t entry_offset = reader.ReadUInt();
      ASSERT(entry_offset < constant_offset);  // DAG!
      const auto& constant = Instance::Handle(Z, ReadConstant(entry_offset));
      ASSERT(!constant.IsNull());

      // Build type from the raw bytes (needs temporary translator).
      TypeTranslator type_translator(
          &reader, this, active_class_, true,
          active_class_->RequireConstCanonicalTypeErasure(null_safety));
      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 kTearOffConstant: {
      const NameIndex index = reader.ReadCanonicalNameReference();
      Function& function =
          Function::Handle(Z, 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_, true);
      instance = type_translator.BuildType().ptr();
      break;
    }
    default:
      // Set literals (kSetConstant) are currently desugared in the frontend
      // and will not reach the VM. See http://dartbug.com/35124 for some
      // discussion. Map constants (kMapConstant ) are already lowered to
      // InstanceConstant or ListConstant. 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
