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

#ifndef DART_PRECOMPILED_RUNTIME

#include "vm/compiler/compiler_state.h"
#include "vm/hash_map.h"
#include "vm/parser.h"
#include "vm/scopes.h"

namespace dart {

// Canonicalization cache for Slot objects.
//
// This cache is attached to the CompilerState to ensure that we preserve
// identity of Slot objects during each individual compilation.
class SlotCache : public ZoneAllocated {
 public:
  // Returns an instance of SlotCache for the current compilation.
  static SlotCache& Instance(Thread* thread) {
    auto result = thread->compiler_state().slot_cache();
    if (result == nullptr) {
      result = new (thread->zone()) SlotCache(thread);
      thread->compiler_state().set_slot_cache(result);
    }
    return *result;
  }

  const Slot& Canonicalize(const Slot& value) {
    auto result = fields_.LookupValue(&value);
    if (result == nullptr) {
      result = new (zone_) Slot(value);
      fields_.Insert(result);
    }
    return *result;
  }

 private:
  explicit SlotCache(Thread* thread)
      : zone_(thread->zone()), fields_(thread->zone()) {}

  Zone* const zone_;
  DirectChainedHashMap<PointerKeyValueTrait<const Slot> > fields_;
};

const Slot& Slot::GetNativeSlot(Kind kind) {
  // There is a fixed statically known number of native slots so we cache
  // them statically.
  static const Slot fields[] = {
#define FIELD_FINAL (IsImmutableBit::encode(true))
#define FIELD_VAR (0)
#define DEFINE_NATIVE_FIELD(ClassName, FieldName, cid, mutability)             \
  Slot(Kind::k##ClassName##_##FieldName, FIELD_##mutability, k##cid##Cid,      \
       ClassName::FieldName##_offset(), #ClassName "." #FieldName, nullptr),

      NATIVE_SLOTS_LIST(DEFINE_NATIVE_FIELD)

#undef DEFINE_FIELD
#undef FIELD_VAR
#undef FIELD_FINAL
  };

  ASSERT(static_cast<uint8_t>(kind) < ARRAY_SIZE(fields));
  return fields[static_cast<uint8_t>(kind)];
}

// Note: should only be called with cids of array-like classes.
const Slot& Slot::GetLengthFieldForArrayCid(intptr_t array_cid) {
  if (RawObject::IsExternalTypedDataClassId(array_cid) ||
      RawObject::IsTypedDataClassId(array_cid)) {
    return GetNativeSlot(Kind::kTypedData_length);
  }

  switch (array_cid) {
    case kGrowableObjectArrayCid:
      return GetNativeSlot(Kind::kGrowableObjectArray_length);

    case kOneByteStringCid:
    case kTwoByteStringCid:
    case kExternalOneByteStringCid:
    case kExternalTwoByteStringCid:
      return GetNativeSlot(Kind::kString_length);

    case kArrayCid:
    case kImmutableArrayCid:
      return GetNativeSlot(Kind::kArray_length);

    default:
      UNREACHABLE();
      return GetNativeSlot(Kind::kArray_length);
  }
}

const Slot& Slot::GetTypeArgumentsSlotAt(Thread* thread, intptr_t offset) {
  ASSERT(offset != Class::kNoTypeArguments);
  return SlotCache::Instance(thread).Canonicalize(Slot(
      Kind::kTypeArguments, IsImmutableBit::encode(true), kTypeArgumentsCid,
      offset, ":type_arguments", /*static_type=*/nullptr));
}

const Slot& Slot::GetTypeArgumentsSlotFor(Thread* thread, const Class& cls) {
  return GetTypeArgumentsSlotAt(thread, cls.type_arguments_field_offset());
}

const Slot& Slot::GetContextVariableSlotFor(Thread* thread,
                                            const LocalVariable& variable) {
  ASSERT(variable.is_captured());
  // TODO(vegorov) Can't assign static type to local variables because
  // for captured parameters we generate the code that first stores a
  // variable into the context and then loads it from the context to perform
  // the type check.
  return SlotCache::Instance(thread).Canonicalize(Slot(
      Kind::kCapturedVariable,
      IsImmutableBit::encode(variable.is_final()) | IsNullableBit::encode(true),
      kDynamicCid, Context::variable_offset(variable.index().value()),
      &variable.name(), /*static_type=*/nullptr));
}

const Slot& Slot::Get(const Field& field,
                      const ParsedFunction* parsed_function) {
  Thread* thread = Thread::Current();
  Zone* zone = thread->zone();
  intptr_t nullable_cid = kDynamicCid;
  bool is_nullable = true;

  if (field.has_pragma()) {
    const intptr_t cid = MethodRecognizer::ResultCidFromPragma(field);
    if (cid != kDynamicCid) {
      nullable_cid = cid;
      is_nullable = false;
    } else if (MethodRecognizer::HasNonNullableResultTypeFromPragma(field)) {
      is_nullable = false;
    }
  }

  if (field.guarded_cid() != kIllegalCid &&
      field.guarded_cid() != kDynamicCid) {
    nullable_cid =
        nullable_cid != kDynamicCid ? nullable_cid : field.guarded_cid();
    is_nullable = is_nullable && field.is_nullable();

    if (thread->isolate()->use_field_guards()) {
      ASSERT(parsed_function != nullptr);
      parsed_function->AddToGuardedFields(&field);
    } else {
      // In precompiled mode we use guarded_cid field for type information
      // inferred by TFA.
      ASSERT(FLAG_precompiled_mode);
    }
  }

  return SlotCache::Instance(thread).Canonicalize(
      Slot(Kind::kDartField,
           IsImmutableBit::encode(field.is_final() || field.is_const()) |
               IsNullableBit::encode(is_nullable),
           nullable_cid, field.Offset(), &field,
           &AbstractType::ZoneHandle(zone, field.type())));
}

CompileType Slot::ComputeCompileType() const {
  return CompileType::CreateNullable(is_nullable(), nullable_cid());
}

const AbstractType& Slot::static_type() const {
  return static_type_ != nullptr ? *static_type_ : Object::null_abstract_type();
}

const char* Slot::Name() const {
  if (IsLocalVariable()) {
    return DataAs<const String>()->ToCString();
  } else if (IsDartField()) {
    return String::Handle(field().name()).ToCString();
  } else {
    return DataAs<const char>();
  }
}

bool Slot::Equals(const Slot* other) const {
  if (kind_ != other->kind_) {
    return false;
  }

  switch (kind_) {
    case Kind::kTypeArguments:
      return (offset_in_bytes_ == other->offset_in_bytes_);

    case Kind::kCapturedVariable:
      return (offset_in_bytes_ == other->offset_in_bytes_) &&
             (flags_ == other->flags_) &&
             (DataAs<const String>()->raw() ==
              other->DataAs<const String>()->raw());

    case Kind::kDartField:
      return (offset_in_bytes_ == other->offset_in_bytes_) &&
             other->DataAs<const Field>()->Original() ==
                 DataAs<const Field>()->Original();

    default:
      UNREACHABLE();
      return false;
  }
}

intptr_t Slot::Hashcode() const {
  intptr_t result = (static_cast<int8_t>(kind_) * 63 + offset_in_bytes_) * 31;
  if (IsDartField()) {
    result += String::Handle(DataAs<const Field>()->name()).Hash();
  } else if (IsLocalVariable()) {
    result += DataAs<const String>()->Hash();
  }
  return result;
}

}  // namespace dart

#endif  // DART_PRECOMPILED_RUNTIME
