blob: 9786c05a9d688ef9a04fdf153c1fc46c10b567b4 [file] [log] [blame]
Nicolas Geoffray524e7ea2015-10-16 17:13:34 +01001/*
2 * Copyright (C) 2011 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include "oat_quick_method_header.h"
18
19#include "art_method.h"
20#include "mapping_table.h"
21#include "scoped_thread_state_change.h"
22#include "thread.h"
23
24namespace art {
25
26OatQuickMethodHeader::OatQuickMethodHeader(
27 uint32_t mapping_table_offset,
28 uint32_t vmap_table_offset,
29 uint32_t gc_map_offset,
30 uint32_t frame_size_in_bytes,
31 uint32_t core_spill_mask,
32 uint32_t fp_spill_mask,
33 uint32_t code_size)
34 : mapping_table_offset_(mapping_table_offset),
35 vmap_table_offset_(vmap_table_offset),
36 gc_map_offset_(gc_map_offset),
37 frame_info_(frame_size_in_bytes, core_spill_mask, fp_spill_mask),
38 code_size_(code_size) {}
39
40OatQuickMethodHeader::~OatQuickMethodHeader() {}
41
42uint32_t OatQuickMethodHeader::ToDexPc(ArtMethod* method,
43 const uintptr_t pc,
44 bool abort_on_failure) const {
45 const void* entry_point = GetEntryPoint();
46 uint32_t sought_offset = pc - reinterpret_cast<uintptr_t>(entry_point);
47 if (IsOptimized()) {
48 CodeInfo code_info = GetOptimizedCodeInfo();
49 StackMapEncoding encoding = code_info.ExtractEncoding();
50 StackMap stack_map = code_info.GetStackMapForNativePcOffset(sought_offset, encoding);
51 if (stack_map.IsValid()) {
52 return stack_map.GetDexPc(encoding);
53 }
54 } else {
55 MappingTable table(GetMappingTable());
56 // NOTE: Special methods (see Mir2Lir::GenSpecialCase()) have an empty mapping
57 // but they have no suspend checks and, consequently, we never call ToDexPc() for them.
58 if (table.TotalSize() == 0) {
59 DCHECK(method->IsNative());
60 return DexFile::kDexNoIndex;
61 }
62
63 // Assume the caller wants a pc-to-dex mapping so check here first.
64 typedef MappingTable::PcToDexIterator It;
65 for (It cur = table.PcToDexBegin(), end = table.PcToDexEnd(); cur != end; ++cur) {
66 if (cur.NativePcOffset() == sought_offset) {
67 return cur.DexPc();
68 }
69 }
70 // Now check dex-to-pc mappings.
71 typedef MappingTable::DexToPcIterator It2;
72 for (It2 cur = table.DexToPcBegin(), end = table.DexToPcEnd(); cur != end; ++cur) {
73 if (cur.NativePcOffset() == sought_offset) {
74 return cur.DexPc();
75 }
76 }
77 }
78 if (abort_on_failure) {
79 ScopedObjectAccess soa(Thread::Current());
80 LOG(FATAL) << "Failed to find Dex offset for PC offset "
81 << reinterpret_cast<void*>(sought_offset)
82 << "(PC " << reinterpret_cast<void*>(pc) << ", entry_point=" << entry_point
83 << " current entry_point=" << method->GetEntryPointFromQuickCompiledCode()
84 << ") in " << PrettyMethod(method);
85 }
86 return DexFile::kDexNoIndex;
87}
88
89uintptr_t OatQuickMethodHeader::ToNativeQuickPc(ArtMethod* method,
90 const uint32_t dex_pc,
91 bool is_for_catch_handler,
92 bool abort_on_failure) const {
93 const void* entry_point = GetEntryPoint();
94 if (IsOptimized()) {
95 // Optimized code does not have a mapping table. Search for the dex-to-pc
96 // mapping in stack maps.
97 CodeInfo code_info = GetOptimizedCodeInfo();
98 StackMapEncoding encoding = code_info.ExtractEncoding();
99
100 // All stack maps are stored in the same CodeItem section, safepoint stack
101 // maps first, then catch stack maps. We use `is_for_catch_handler` to select
102 // the order of iteration.
103 StackMap stack_map =
104 LIKELY(is_for_catch_handler) ? code_info.GetCatchStackMapForDexPc(dex_pc, encoding)
105 : code_info.GetStackMapForDexPc(dex_pc, encoding);
106 if (stack_map.IsValid()) {
107 return reinterpret_cast<uintptr_t>(entry_point) + stack_map.GetNativePcOffset(encoding);
108 }
109 } else {
110 MappingTable table(GetMappingTable());
111 if (table.TotalSize() == 0) {
112 DCHECK_EQ(dex_pc, 0U);
113 return 0; // Special no mapping/pc == 0 case
114 }
115 // Assume the caller wants a dex-to-pc mapping so check here first.
116 typedef MappingTable::DexToPcIterator It;
117 for (It cur = table.DexToPcBegin(), end = table.DexToPcEnd(); cur != end; ++cur) {
118 if (cur.DexPc() == dex_pc) {
119 return reinterpret_cast<uintptr_t>(entry_point) + cur.NativePcOffset();
120 }
121 }
122 // Now check pc-to-dex mappings.
123 typedef MappingTable::PcToDexIterator It2;
124 for (It2 cur = table.PcToDexBegin(), end = table.PcToDexEnd(); cur != end; ++cur) {
125 if (cur.DexPc() == dex_pc) {
126 return reinterpret_cast<uintptr_t>(entry_point) + cur.NativePcOffset();
127 }
128 }
129 }
130
131 if (abort_on_failure) {
132 ScopedObjectAccess soa(Thread::Current());
133 LOG(FATAL) << "Failed to find native offset for dex pc 0x" << std::hex << dex_pc
134 << " in " << PrettyMethod(method);
135 }
136 return UINTPTR_MAX;
137}
138
139} // namespace art