/*
 * 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 "dex/dex_file_types.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 dex::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 dex::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
