/*
 * Copyright (C) 2011 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.
 */

#ifndef ART_RUNTIME_OAT_QUICK_METHOD_HEADER_H_
#define ART_RUNTIME_OAT_QUICK_METHOD_HEADER_H_

#include "arch/instruction_set.h"
#include "base/locks.h"
#include "base/macros.h"
#include "base/utils.h"
#include "quick/quick_method_frame_info.h"
#include "stack_map.h"

namespace art {

class ArtMethod;

// OatQuickMethodHeader precedes the raw code chunk generated by the compiler.
class PACKED(4) OatQuickMethodHeader {
 public:
  OatQuickMethodHeader(uint32_t code_info_offset = 0) {
    SetCodeInfoOffset(code_info_offset);
  }

  static OatQuickMethodHeader* NterpMethodHeader;

  bool IsNterpMethodHeader() const;

  static bool IsNterpPc(uintptr_t pc) {
    return OatQuickMethodHeader::NterpMethodHeader != nullptr &&
        OatQuickMethodHeader::NterpMethodHeader->Contains(pc);
  }

  static OatQuickMethodHeader* FromCodePointer(const void* code_ptr) {
    uintptr_t code = reinterpret_cast<uintptr_t>(code_ptr);
    uintptr_t header = code - OFFSETOF_MEMBER(OatQuickMethodHeader, code_);
    DCHECK(IsAlignedParam(code, GetInstructionSetAlignment(kRuntimeISA)) ||
           IsAlignedParam(header, GetInstructionSetAlignment(kRuntimeISA)))
        << std::hex << code << " " << std::hex << header;
    return reinterpret_cast<OatQuickMethodHeader*>(header);
  }

  static OatQuickMethodHeader* FromEntryPoint(const void* entry_point) {
    return FromCodePointer(EntryPointToCodePointer(entry_point));
  }

  static size_t InstructionAlignedSize() {
    return RoundUp(sizeof(OatQuickMethodHeader), GetInstructionSetAlignment(kRuntimeISA));
  }

  OatQuickMethodHeader(const OatQuickMethodHeader&) = default;
  OatQuickMethodHeader& operator=(const OatQuickMethodHeader&) = default;

  uintptr_t NativeQuickPcOffset(const uintptr_t pc) const {
    return pc - reinterpret_cast<uintptr_t>(GetEntryPoint());
  }

  ALWAYS_INLINE bool IsOptimized() const {
    uintptr_t code = reinterpret_cast<uintptr_t>(code_);
    DCHECK_NE(data_, 0u) << std::hex << code;          // Probably a padding of native code.
    DCHECK_NE(data_, kInvalidData) << std::hex << code;  // Probably a stub or trampoline.
    return (data_ & kIsCodeInfoMask) != 0;
  }

  ALWAYS_INLINE const uint8_t* GetOptimizedCodeInfoPtr() const {
    uint32_t offset = GetCodeInfoOffset();
    DCHECK_NE(offset, 0u);
    return code_ - offset;
  }

  ALWAYS_INLINE uint8_t* GetOptimizedCodeInfoPtr() {
    uint32_t offset = GetCodeInfoOffset();
    DCHECK_NE(offset, 0u);
    return code_ - offset;
  }

  ALWAYS_INLINE const uint8_t* GetCode() const {
    return code_;
  }

  ALWAYS_INLINE uint32_t GetCodeSize() const {
    return LIKELY(IsOptimized())
        ? CodeInfo::DecodeCodeSize(GetOptimizedCodeInfoPtr())
        : (data_ & kCodeSizeMask);
  }

  ALWAYS_INLINE uint32_t GetCodeInfoOffset() const {
    DCHECK(IsOptimized());
    return data_ & kCodeInfoMask;
  }

  void SetCodeInfoOffset(uint32_t offset) {
    data_ = kIsCodeInfoMask | offset;
    DCHECK_EQ(GetCodeInfoOffset(), offset);
  }

  bool Contains(uintptr_t pc) const {
    // We should not call `Contains` on a stub or trampoline.
    DCHECK_NE(data_, kInvalidData) << std::hex << reinterpret_cast<uintptr_t>(code_);
    // Remove hwasan tag to make comparison below valid. The PC from the stack does not have it.
    uintptr_t code_start = reinterpret_cast<uintptr_t>(HWASanUntag(code_));
    static_assert(kRuntimeISA != InstructionSet::kThumb2, "kThumb2 cannot be a runtime ISA");
    if (kRuntimeISA == InstructionSet::kArm) {
      // On Thumb-2, the pc is offset by one.
      code_start++;
    }
    return code_start <= pc && pc <= (code_start + GetCodeSize());
  }

  const uint8_t* GetEntryPoint() const {
    // When the runtime architecture is ARM, `kRuntimeISA` is set to `kArm`
    // (not `kThumb2`), *but* we always generate code for the Thumb-2
    // instruction set anyway. Thumb-2 requires the entrypoint to be of
    // offset 1.
    static_assert(kRuntimeISA != InstructionSet::kThumb2, "kThumb2 cannot be a runtime ISA");
    return (kRuntimeISA == InstructionSet::kArm)
        ? reinterpret_cast<uint8_t*>(reinterpret_cast<uintptr_t>(code_) | 1)
        : code_;
  }

  template <bool kCheckFrameSize = true>
  uint32_t GetFrameSizeInBytes() const {
    uint32_t result = GetFrameInfo().FrameSizeInBytes();
    if (kCheckFrameSize) {
      DCHECK_ALIGNED(result, kStackAlignment);
    }
    return result;
  }

  QuickMethodFrameInfo GetFrameInfo() const {
    DCHECK(IsOptimized());
    return CodeInfo::DecodeFrameInfo(GetOptimizedCodeInfoPtr());
  }

  uintptr_t ToNativeQuickPc(ArtMethod* method,
                            const uint32_t dex_pc,
                            bool is_for_catch_handler,
                            bool abort_on_failure = true) const;

  uint32_t ToDexPc(ArtMethod** frame,
                   const uintptr_t pc,
                   bool abort_on_failure = true) const
      REQUIRES_SHARED(Locks::mutator_lock_);

  void SetHasShouldDeoptimizeFlag() {
    DCHECK(!HasShouldDeoptimizeFlag());
    data_ |= kShouldDeoptimizeMask;
  }

  bool HasShouldDeoptimizeFlag() const {
    return (data_ & kShouldDeoptimizeMask) != 0;
  }

 private:
  static constexpr uint32_t kShouldDeoptimizeMask = 0x80000000;
  static constexpr uint32_t kIsCodeInfoMask       = 0x40000000;
  static constexpr uint32_t kCodeInfoMask         = 0x3FFFFFFF;  // If kIsCodeInfoMask is set.
  static constexpr uint32_t kCodeSizeMask         = 0x3FFFFFFF;  // If kIsCodeInfoMask is clear.

  // In order to not confuse a stub with Java-generated code, we prefix each
  // stub with a 0xFFFFFFFF marker.
  static constexpr uint32_t kInvalidData = 0xFFFFFFFF;

  uint32_t data_ = 0u;  // Combination of fields using the above masks.
  uint8_t code_[0];     // The actual method code.
};

}  // namespace art

#endif  // ART_RUNTIME_OAT_QUICK_METHOD_HEADER_H_
