/*
 * 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.
 */

#include "oat_quick_method_header.h"

#include "art_method.h"
#include "scoped_thread_state_change-inl.h"
#include "thread.h"

namespace art {

OatQuickMethodHeader::OatQuickMethodHeader(uint32_t vmap_table_offset,
                                           uint32_t method_info_offset,
                                           uint32_t frame_size_in_bytes,
                                           uint32_t core_spill_mask,
                                           uint32_t fp_spill_mask,
                                           uint32_t code_size)
    : vmap_table_offset_(vmap_table_offset),
      method_info_offset_(method_info_offset),
      frame_info_(frame_size_in_bytes, core_spill_mask, fp_spill_mask),
      code_size_(code_size) {}

OatQuickMethodHeader::~OatQuickMethodHeader() {}

uint32_t OatQuickMethodHeader::ToDexPc(ArtMethod* method,
                                       const uintptr_t pc,
                                       bool abort_on_failure) const {
  const void* entry_point = GetEntryPoint();
  uint32_t sought_offset = pc - reinterpret_cast<uintptr_t>(entry_point);
  if (IsOptimized()) {
    CodeInfo code_info = GetOptimizedCodeInfo();
    CodeInfoEncoding encoding = code_info.ExtractEncoding();
    StackMap stack_map = code_info.GetStackMapForNativePcOffset(sought_offset, encoding);
    if (stack_map.IsValid()) {
      return stack_map.GetDexPc(encoding.stack_map.encoding);
    }
  } else {
    DCHECK(method->IsNative());
    return DexFile::kDexNoIndex;
  }
  if (abort_on_failure) {
    ScopedObjectAccess soa(Thread::Current());
    LOG(FATAL) << "Failed to find Dex offset for PC offset "
           << reinterpret_cast<void*>(sought_offset)
           << "(PC " << reinterpret_cast<void*>(pc) << ", entry_point=" << entry_point
           << " current entry_point=" << method->GetEntryPointFromQuickCompiledCode()
           << ") in " << method->PrettyMethod();
  }
  return DexFile::kDexNoIndex;
}

uintptr_t OatQuickMethodHeader::ToNativeQuickPc(ArtMethod* method,
                                                const uint32_t dex_pc,
                                                bool is_for_catch_handler,
                                                bool abort_on_failure) const {
  const void* entry_point = GetEntryPoint();
  DCHECK(!method->IsNative());
  DCHECK(IsOptimized());
  // Search for the dex-to-pc mapping in stack maps.
  CodeInfo code_info = GetOptimizedCodeInfo();
  CodeInfoEncoding encoding = code_info.ExtractEncoding();

  // All stack maps are stored in the same CodeItem section, safepoint stack
  // maps first, then catch stack maps. We use `is_for_catch_handler` to select
  // the order of iteration.
  StackMap stack_map =
      LIKELY(is_for_catch_handler) ? code_info.GetCatchStackMapForDexPc(dex_pc, encoding)
                                   : code_info.GetStackMapForDexPc(dex_pc, encoding);
  if (stack_map.IsValid()) {
    return reinterpret_cast<uintptr_t>(entry_point) +
           stack_map.GetNativePcOffset(encoding.stack_map.encoding, kRuntimeISA);
  }
  if (abort_on_failure) {
    ScopedObjectAccess soa(Thread::Current());
    LOG(FATAL) << "Failed to find native offset for dex pc 0x" << std::hex << dex_pc
               << " in " << method->PrettyMethod();
  }
  return UINTPTR_MAX;
}

}  // namespace art
