/*
 * Copyright (C) 2015 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "lambda/closure.h"

#include "base/logging.h"
#include "lambda/art_lambda_method.h"
#include "runtime/mirror/object_reference.h"

namespace art {
namespace lambda {

template <typename T>
// TODO: can I return T __attribute__((__aligned__(1)))* here instead?
const uint8_t* Closure::GetUnsafeAtOffset(size_t offset) const {
  // Do not DCHECK here with existing helpers since most of them will call into this function.
  return reinterpret_cast<const uint8_t*>(captured_) + offset;
}

size_t Closure::GetCapturedVariableSize(ShortyFieldType variable_type, size_t offset) const {
  switch (variable_type) {
    case ShortyFieldType::kLambda:
    {
      return GetClosureSize(GetUnsafeAtOffset<Closure>(offset));
    }
    default:
      DCHECK(variable_type.IsStaticSize());
      return variable_type.GetStaticSize();
  }
}

// Templatize the flags to give the compiler a fighting chance to eliminate
// any unnecessary code through different uses of this function.
template <Closure::VariableInfo::Flags flags>
inline Closure::VariableInfo Closure::ParseTypeDescriptor(const char* type_descriptor,
                                                          size_t upto_index) const {
  DCHECK(type_descriptor != nullptr);

  VariableInfo result;

  ShortyFieldType last_type;
  size_t offset = (flags & VariableInfo::kOffset) ? GetStartingOffset() : 0;
  size_t prev_offset = 0;
  size_t count = 0;

  while ((type_descriptor =
      ShortyFieldType::ParseFromFieldTypeDescriptor(type_descriptor, &last_type)) != nullptr) {
    count++;

    if (flags & VariableInfo::kOffset) {
      // Accumulate the sizes of all preceding captured variables as the current offset only.
      offset += prev_offset;
      prev_offset = GetCapturedVariableSize(last_type, offset);
    }

    if ((count > upto_index)) {
      break;
    }
  }

  if (flags & VariableInfo::kVariableType) {
    result.variable_type_ = last_type;
  }

  if (flags & VariableInfo::kIndex) {
    result.index_ = count;
  }

  if (flags & VariableInfo::kCount) {
    result.count_ = count;
  }

  if (flags & VariableInfo::kOffset) {
    result.offset_ = offset;
  }

  // TODO: We should probably store the result of this in the ArtLambdaMethod,
  // to avoid re-computing the data every single time for static closures.
  return result;
}

size_t Closure::GetCapturedVariablesSize() const {
  const size_t captured_variable_offset = offsetof(Closure, captured_);
  DCHECK_GE(GetSize(), captured_variable_offset);  // Prevent underflows.
  return GetSize() - captured_variable_offset;
}

size_t Closure::GetSize() const {
  const size_t static_closure_size = lambda_info_->GetStaticClosureSize();
  if (LIKELY(lambda_info_->IsStaticSize())) {
    return static_closure_size;
  }

  DCHECK_GE(static_closure_size, sizeof(captured_[0].dynamic_.size_));
  const size_t dynamic_closure_size = captured_[0].dynamic_.size_;
  // The dynamic size better be at least as big as the static size.
  DCHECK_GE(dynamic_closure_size, static_closure_size);

  return dynamic_closure_size;
}

void Closure::CopyTo(void* target, size_t target_size) const {
  DCHECK_GE(target_size, GetSize());

  // TODO: using memcpy is unsafe with read barriers, fix this once we add reference support
  static_assert(kClosureSupportsReferences == false,
                "Do not use memcpy with readbarrier references");
  memcpy(target, this, GetSize());
}

ArtMethod* Closure::GetTargetMethod() const {
  return const_cast<ArtMethod*>(lambda_info_->GetArtMethod());
}

ArtLambdaMethod* Closure::GetLambdaInfo() const {
  return const_cast<ArtLambdaMethod*>(lambda_info_);
}

uint32_t Closure::GetHashCode() const {
  // Start with a non-zero constant, a prime number.
  uint32_t result = 17;

  // Include the hash with the ArtMethod.
  {
    uintptr_t method = reinterpret_cast<uintptr_t>(GetTargetMethod());
    result = 31 * result + Low32Bits(method);
    if (sizeof(method) == sizeof(uint64_t)) {
      result = 31 * result + High32Bits(method);
    }
  }

  // Include a hash for each captured variable.
  for (size_t i = 0; i < GetCapturedVariablesSize(); ++i) {
    // TODO: not safe for GC-able values since the address can move and the hash code would change.
    uint8_t captured_variable_raw_value;
    CopyUnsafeAtOffset<uint8_t>(i, /*out*/&captured_variable_raw_value);  // NOLINT: [whitespace/comma] [3]

    result = 31 * result + captured_variable_raw_value;
  }

  // TODO: Fix above loop to work for objects and lambdas.
  static_assert(kClosureSupportsGarbageCollection == false,
               "Need to update above loop to read the hash code from the "
                "objects and lambdas recursively");

  return result;
}

bool Closure::ReferenceEquals(const Closure* other) const {
  DCHECK(other != nullptr);

  // TODO: Need rework to use read barriers once closures have references inside of them that can
  // move. Until then, it's safe to just compare the data inside of it directly.
  static_assert(kClosureSupportsReferences == false,
                "Unsafe to use memcmp in read barrier collector");

  if (GetSize() != other->GetSize()) {
    return false;
  }

  return memcmp(this, other, GetSize());
}

size_t Closure::GetNumberOfCapturedVariables() const {
  // TODO: refactor into art_lambda_method.h. Parsing should only be required here as a DCHECK.
  VariableInfo variable_info =
      ParseTypeDescriptor<VariableInfo::kCount>(GetCapturedVariablesTypeDescriptor(),
                                                VariableInfo::kUpToIndexMax);
  size_t count = variable_info.count_;
  // Assuming each variable was 1 byte, the size should always be greater or equal than the count.
  DCHECK_LE(count, GetCapturedVariablesSize());
  return count;
}

const char* Closure::GetCapturedVariablesTypeDescriptor() const {
  return lambda_info_->GetCapturedVariablesTypeDescriptor();
}

ShortyFieldType Closure::GetCapturedShortyType(size_t index) const {
  DCHECK_LT(index, GetNumberOfCapturedVariables());

  VariableInfo variable_info =
      ParseTypeDescriptor<VariableInfo::kVariableType>(GetCapturedVariablesTypeDescriptor(),
                                                       index);

  return variable_info.variable_type_;
}

uint32_t Closure::GetCapturedPrimitiveNarrow(size_t index) const {
  DCHECK(GetCapturedShortyType(index).IsPrimitiveNarrow());

  ShortyFieldType variable_type;
  size_t offset;
  GetCapturedVariableTypeAndOffset(index, &variable_type, &offset);

  // TODO: Restructure to use template specialization, e.g. GetCapturedPrimitive<T>
  // so that we can avoid this nonsense regarding memcpy always overflowing.
  // Plus, this additional switching seems redundant since the interpreter
  // would've done it already, and knows the exact type.
  uint32_t result = 0;
  static_assert(ShortyFieldTypeTraits::IsPrimitiveNarrowType<decltype(result)>(),
                "result must be a primitive narrow type");
  switch (variable_type) {
    case ShortyFieldType::kBoolean:
      CopyUnsafeAtOffset<bool>(offset, &result);
      break;
    case ShortyFieldType::kByte:
      CopyUnsafeAtOffset<uint8_t>(offset, &result);
      break;
    case ShortyFieldType::kChar:
      CopyUnsafeAtOffset<uint16_t>(offset, &result);
      break;
    case ShortyFieldType::kShort:
      CopyUnsafeAtOffset<int16_t>(offset, &result);
      break;
    case ShortyFieldType::kInt:
      CopyUnsafeAtOffset<int32_t>(offset, &result);
      break;
    case ShortyFieldType::kFloat:
      // XX: Maybe there should just be a GetCapturedPrimitive<T> to avoid this shuffle?
      // The interpreter's invoke seems to only special case references and wides,
      // everything else is treated as a generic 32-bit pattern.
      CopyUnsafeAtOffset<float>(offset, &result);
      break;
    default:
      LOG(FATAL)
          << "expected a valid narrow primitive shorty type but got "
          << static_cast<char>(variable_type);
      UNREACHABLE();
  }

  return result;
}

uint64_t Closure::GetCapturedPrimitiveWide(size_t index) const {
  DCHECK(GetCapturedShortyType(index).IsPrimitiveWide());

  ShortyFieldType variable_type;
  size_t offset;
  GetCapturedVariableTypeAndOffset(index, &variable_type, &offset);

  // TODO: Restructure to use template specialization, e.g. GetCapturedPrimitive<T>
  // so that we can avoid this nonsense regarding memcpy always overflowing.
  // Plus, this additional switching seems redundant since the interpreter
  // would've done it already, and knows the exact type.
  uint64_t result = 0;
  static_assert(ShortyFieldTypeTraits::IsPrimitiveWideType<decltype(result)>(),
                "result must be a primitive wide type");
  switch (variable_type) {
    case ShortyFieldType::kLong:
      CopyUnsafeAtOffset<int64_t>(offset, &result);
      break;
    case ShortyFieldType::kDouble:
      CopyUnsafeAtOffset<double>(offset, &result);
      break;
    default:
      LOG(FATAL)
          << "expected a valid primitive wide shorty type but got "
          << static_cast<char>(variable_type);
      UNREACHABLE();
  }

  return result;
}

mirror::Object* Closure::GetCapturedObject(size_t index) const {
  DCHECK(GetCapturedShortyType(index).IsObject());

  ShortyFieldType variable_type;
  size_t offset;
  GetCapturedVariableTypeAndOffset(index, &variable_type, &offset);

  // TODO: Restructure to use template specialization, e.g. GetCapturedPrimitive<T>
  // so that we can avoid this nonsense regarding memcpy always overflowing.
  // Plus, this additional switching seems redundant since the interpreter
  // would've done it already, and knows the exact type.
  mirror::Object* result = nullptr;
  static_assert(ShortyFieldTypeTraits::IsObjectType<decltype(result)>(),
                "result must be an object type");
  switch (variable_type) {
    case ShortyFieldType::kObject:
      // TODO: This seems unsafe. This may need to use gcroots.
      static_assert(kClosureSupportsGarbageCollection == false,
                    "May need GcRoots and definitely need mutator locks");
      {
        mirror::CompressedReference<mirror::Object> compressed_result;
        CopyUnsafeAtOffset<uint32_t>(offset, &compressed_result);
        result = compressed_result.AsMirrorPtr();
      }
      break;
    default:
      CHECK(false)
          << "expected a valid shorty type but got " << static_cast<char>(variable_type);
      UNREACHABLE();
  }

  return result;
}

size_t Closure::GetCapturedClosureSize(size_t index) const {
  DCHECK(GetCapturedShortyType(index).IsLambda());
  size_t offset = GetCapturedVariableOffset(index);

  auto* captured_ptr = reinterpret_cast<const uint8_t*>(&captured_);
  size_t closure_size = GetClosureSize(captured_ptr + offset);

  return closure_size;
}

void Closure::CopyCapturedClosure(size_t index, void* destination, size_t destination_room) const {
  DCHECK(GetCapturedShortyType(index).IsLambda());
  size_t offset = GetCapturedVariableOffset(index);

  auto* captured_ptr = reinterpret_cast<const uint8_t*>(&captured_);
  size_t closure_size = GetClosureSize(captured_ptr + offset);

  static_assert(ShortyFieldTypeTraits::IsLambdaType<Closure*>(),
                "result must be a lambda type");

  CopyUnsafeAtOffset<Closure>(offset, destination, closure_size, destination_room);
}

size_t Closure::GetCapturedVariableOffset(size_t index) const {
  VariableInfo variable_info =
      ParseTypeDescriptor<VariableInfo::kOffset>(GetCapturedVariablesTypeDescriptor(),
                                                 index);

  size_t offset = variable_info.offset_;

  return offset;
}

void Closure::GetCapturedVariableTypeAndOffset(size_t index,
                                               ShortyFieldType* out_type,
                                               size_t* out_offset) const {
  DCHECK(out_type != nullptr);
  DCHECK(out_offset != nullptr);

  static constexpr const VariableInfo::Flags kVariableTypeAndOffset =
      static_cast<VariableInfo::Flags>(VariableInfo::kVariableType | VariableInfo::kOffset);
  VariableInfo variable_info =
      ParseTypeDescriptor<kVariableTypeAndOffset>(GetCapturedVariablesTypeDescriptor(),
                                                  index);

  ShortyFieldType variable_type = variable_info.variable_type_;
  size_t offset = variable_info.offset_;

  *out_type = variable_type;
  *out_offset = offset;
}

template <typename T>
void Closure::CopyUnsafeAtOffset(size_t offset,
                                 void* destination,
                                 size_t src_size,
                                 size_t destination_room) const {
  DCHECK_GE(destination_room, src_size);
  const uint8_t* data_ptr = GetUnsafeAtOffset<T>(offset);
  memcpy(destination, data_ptr, sizeof(T));
}

// TODO: This is kind of ugly. I would prefer an unaligned_ptr<Closure> here.
// Unfortunately C++ doesn't let you lower the alignment (i.e. alignas(1) Closure*) is not legal.
size_t Closure::GetClosureSize(const uint8_t* closure) {
  DCHECK(closure != nullptr);

  static_assert(!std::is_base_of<mirror::Object, Closure>::value,
                "It might be unsafe to call memcpy on a managed object");

  // Safe as long as it's not a mirror Object.
  // TODO: Should probably wrap this in like MemCpyNative or some such which statically asserts
  // we aren't trying to copy mirror::Object data around.
  ArtLambdaMethod* closure_info;
  memcpy(&closure_info, closure + offsetof(Closure, lambda_info_), sizeof(closure_info));

  if (LIKELY(closure_info->IsStaticSize())) {
    return closure_info->GetStaticClosureSize();
  }

  // The size is dynamic, so we need to read it from captured_variables_ portion.
  size_t dynamic_size;
  memcpy(&dynamic_size,
         closure + offsetof(Closure, captured_[0].dynamic_.size_),
         sizeof(dynamic_size));
  static_assert(sizeof(dynamic_size) == sizeof(captured_[0].dynamic_.size_),
                "Dynamic size type must match the structural type of the size");

  DCHECK_GE(dynamic_size, closure_info->GetStaticClosureSize());
  return dynamic_size;
}

size_t Closure::GetStartingOffset() const {
  static constexpr const size_t captured_offset = offsetof(Closure, captured_);
  if (LIKELY(lambda_info_->IsStaticSize())) {
    return offsetof(Closure, captured_[0].static_variables_) - captured_offset;
  } else {
    return offsetof(Closure, captured_[0].dynamic_.variables_) - captured_offset;
  }
}

}  // namespace lambda
}  // namespace art
