1524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray/* 2524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray * Copyright (C) 2011 The Android Open Source Project 3524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray * 4524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray * Licensed under the Apache License, Version 2.0 (the "License"); 5524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray * you may not use this file except in compliance with the License. 6524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray * You may obtain a copy of the License at 7524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray * 8524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray * http://www.apache.org/licenses/LICENSE-2.0 9524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray * 10524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray * Unless required by applicable law or agreed to in writing, software 11524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray * distributed under the License is distributed on an "AS IS" BASIS, 12524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray * See the License for the specific language governing permissions and 14524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray * limitations under the License. 15524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray */ 16524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray 17524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray#include "oat_quick_method_header.h" 18524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray 19524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray#include "art_method.h" 20524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray#include "scoped_thread_state_change.h" 21524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray#include "thread.h" 22524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray 23524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffraynamespace art { 24524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray 25524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas GeoffrayOatQuickMethodHeader::OatQuickMethodHeader( 26524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray uint32_t vmap_table_offset, 27524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray uint32_t frame_size_in_bytes, 28524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray uint32_t core_spill_mask, 29524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray uint32_t fp_spill_mask, 30524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray uint32_t code_size) 319d07e3d128ccfa0ef7670feadd424a825e447d1dVladimir Marko : vmap_table_offset_(vmap_table_offset), 32524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray frame_info_(frame_size_in_bytes, core_spill_mask, fp_spill_mask), 33524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray code_size_(code_size) {} 34524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray 35524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas GeoffrayOatQuickMethodHeader::~OatQuickMethodHeader() {} 36524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray 37524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffrayuint32_t OatQuickMethodHeader::ToDexPc(ArtMethod* method, 38524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray const uintptr_t pc, 39524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray bool abort_on_failure) const { 40524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray const void* entry_point = GetEntryPoint(); 41524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray uint32_t sought_offset = pc - reinterpret_cast<uintptr_t>(entry_point); 42524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray if (IsOptimized()) { 43524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray CodeInfo code_info = GetOptimizedCodeInfo(); 4409ed09866da6d8c7448ef297c148bfa577a247c2David Srbecky CodeInfoEncoding encoding = code_info.ExtractEncoding(); 45524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray StackMap stack_map = code_info.GetStackMapForNativePcOffset(sought_offset, encoding); 46524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray if (stack_map.IsValid()) { 4709ed09866da6d8c7448ef297c148bfa577a247c2David Srbecky return stack_map.GetDexPc(encoding.stack_map_encoding); 48524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray } 49524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray } else { 509d07e3d128ccfa0ef7670feadd424a825e447d1dVladimir Marko DCHECK(method->IsNative()); 519d07e3d128ccfa0ef7670feadd424a825e447d1dVladimir Marko return DexFile::kDexNoIndex; 52524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray } 53524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray if (abort_on_failure) { 54524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray ScopedObjectAccess soa(Thread::Current()); 55524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray LOG(FATAL) << "Failed to find Dex offset for PC offset " 56524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray << reinterpret_cast<void*>(sought_offset) 57524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray << "(PC " << reinterpret_cast<void*>(pc) << ", entry_point=" << entry_point 58524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray << " current entry_point=" << method->GetEntryPointFromQuickCompiledCode() 59524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray << ") in " << PrettyMethod(method); 60524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray } 61524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray return DexFile::kDexNoIndex; 62524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray} 63524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray 64524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffrayuintptr_t OatQuickMethodHeader::ToNativeQuickPc(ArtMethod* method, 65524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray const uint32_t dex_pc, 66524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray bool is_for_catch_handler, 67524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray bool abort_on_failure) const { 68524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray const void* entry_point = GetEntryPoint(); 699d07e3d128ccfa0ef7670feadd424a825e447d1dVladimir Marko DCHECK(!method->IsNative()); 709d07e3d128ccfa0ef7670feadd424a825e447d1dVladimir Marko DCHECK(IsOptimized()); 719d07e3d128ccfa0ef7670feadd424a825e447d1dVladimir Marko // Search for the dex-to-pc mapping in stack maps. 729d07e3d128ccfa0ef7670feadd424a825e447d1dVladimir Marko CodeInfo code_info = GetOptimizedCodeInfo(); 739d07e3d128ccfa0ef7670feadd424a825e447d1dVladimir Marko CodeInfoEncoding encoding = code_info.ExtractEncoding(); 74524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray 759d07e3d128ccfa0ef7670feadd424a825e447d1dVladimir Marko // All stack maps are stored in the same CodeItem section, safepoint stack 769d07e3d128ccfa0ef7670feadd424a825e447d1dVladimir Marko // maps first, then catch stack maps. We use `is_for_catch_handler` to select 779d07e3d128ccfa0ef7670feadd424a825e447d1dVladimir Marko // the order of iteration. 789d07e3d128ccfa0ef7670feadd424a825e447d1dVladimir Marko StackMap stack_map = 799d07e3d128ccfa0ef7670feadd424a825e447d1dVladimir Marko LIKELY(is_for_catch_handler) ? code_info.GetCatchStackMapForDexPc(dex_pc, encoding) 809d07e3d128ccfa0ef7670feadd424a825e447d1dVladimir Marko : code_info.GetStackMapForDexPc(dex_pc, encoding); 819d07e3d128ccfa0ef7670feadd424a825e447d1dVladimir Marko if (stack_map.IsValid()) { 829d07e3d128ccfa0ef7670feadd424a825e447d1dVladimir Marko return reinterpret_cast<uintptr_t>(entry_point) + 839d07e3d128ccfa0ef7670feadd424a825e447d1dVladimir Marko stack_map.GetNativePcOffset(encoding.stack_map_encoding); 84524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray } 85524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray if (abort_on_failure) { 86524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray ScopedObjectAccess soa(Thread::Current()); 87524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray LOG(FATAL) << "Failed to find native offset for dex pc 0x" << std::hex << dex_pc 88524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray << " in " << PrettyMethod(method); 89524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray } 90524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray return UINTPTR_MAX; 91524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray} 92524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray 93524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray} // namespace art 94