blob: 6b84c8faa20ff66b9e0ef1121c6dc9d2960a0041 [file] [log] [blame]
Vladimir Markoe3e02602014-03-12 15:42:41 +00001/*
2 * Copyright (C) 2014 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 "inline_method_analyser.h"
Mathieu Chartierc7853442015-03-27 14:35:38 -070018
19#include "art_field-inl.h"
Mathieu Chartiere401d142015-04-22 13:56:20 -070020#include "art_method-inl.h"
Vladimir Marko3481ba22015-04-13 12:22:36 +010021#include "class_linker-inl.h"
Elliott Hughes956af0f2014-12-11 14:34:28 -080022#include "dex_file-inl.h"
Vladimir Markoe3e02602014-03-12 15:42:41 +000023#include "dex_instruction.h"
24#include "dex_instruction-inl.h"
Vladimir Markoe3e02602014-03-12 15:42:41 +000025#include "mirror/class-inl.h"
Vladimir Markoe3e02602014-03-12 15:42:41 +000026#include "mirror/dex_cache-inl.h"
Vladimir Markoe3e02602014-03-12 15:42:41 +000027#include "verifier/method_verifier-inl.h"
28
29/*
30 * NOTE: This code is part of the quick compiler. It lives in the runtime
31 * only to allow the debugger to check whether a method has been inlined.
32 */
33
34namespace art {
35
Andreas Gampe575e78c2014-11-03 23:41:03 -080036static_assert(InlineMethodAnalyser::IsInstructionIGet(Instruction::IGET), "iget type");
37static_assert(InlineMethodAnalyser::IsInstructionIGet(Instruction::IGET_WIDE), "iget_wide type");
38static_assert(InlineMethodAnalyser::IsInstructionIGet(Instruction::IGET_OBJECT),
39 "iget_object type");
40static_assert(InlineMethodAnalyser::IsInstructionIGet(Instruction::IGET_BOOLEAN),
41 "iget_boolean type");
42static_assert(InlineMethodAnalyser::IsInstructionIGet(Instruction::IGET_BYTE), "iget_byte type");
43static_assert(InlineMethodAnalyser::IsInstructionIGet(Instruction::IGET_CHAR), "iget_char type");
44static_assert(InlineMethodAnalyser::IsInstructionIGet(Instruction::IGET_SHORT), "iget_short type");
45static_assert(InlineMethodAnalyser::IsInstructionIPut(Instruction::IPUT), "iput type");
46static_assert(InlineMethodAnalyser::IsInstructionIPut(Instruction::IPUT_WIDE), "iput_wide type");
47static_assert(InlineMethodAnalyser::IsInstructionIPut(Instruction::IPUT_OBJECT),
48 "iput_object type");
49static_assert(InlineMethodAnalyser::IsInstructionIPut(Instruction::IPUT_BOOLEAN),
50 "iput_boolean type");
51static_assert(InlineMethodAnalyser::IsInstructionIPut(Instruction::IPUT_BYTE), "iput_byte type");
52static_assert(InlineMethodAnalyser::IsInstructionIPut(Instruction::IPUT_CHAR), "iput_char type");
53static_assert(InlineMethodAnalyser::IsInstructionIPut(Instruction::IPUT_SHORT), "iput_short type");
54static_assert(InlineMethodAnalyser::IGetVariant(Instruction::IGET) ==
55 InlineMethodAnalyser::IPutVariant(Instruction::IPUT), "iget/iput variant");
56static_assert(InlineMethodAnalyser::IGetVariant(Instruction::IGET_WIDE) ==
57 InlineMethodAnalyser::IPutVariant(Instruction::IPUT_WIDE), "iget/iput_wide variant");
58static_assert(InlineMethodAnalyser::IGetVariant(Instruction::IGET_OBJECT) ==
59 InlineMethodAnalyser::IPutVariant(Instruction::IPUT_OBJECT), "iget/iput_object variant");
60static_assert(InlineMethodAnalyser::IGetVariant(Instruction::IGET_BOOLEAN) ==
61 InlineMethodAnalyser::IPutVariant(Instruction::IPUT_BOOLEAN), "iget/iput_boolean variant");
62static_assert(InlineMethodAnalyser::IGetVariant(Instruction::IGET_BYTE) ==
63 InlineMethodAnalyser::IPutVariant(Instruction::IPUT_BYTE), "iget/iput_byte variant");
64static_assert(InlineMethodAnalyser::IGetVariant(Instruction::IGET_CHAR) ==
65 InlineMethodAnalyser::IPutVariant(Instruction::IPUT_CHAR), "iget/iput_char variant");
66static_assert(InlineMethodAnalyser::IGetVariant(Instruction::IGET_SHORT) ==
67 InlineMethodAnalyser::IPutVariant(Instruction::IPUT_SHORT), "iget/iput_short variant");
Vladimir Markoe3e02602014-03-12 15:42:41 +000068
Sebastien Hertz2c87c4d2014-03-21 11:31:51 +010069// This is used by compiler and debugger. We look into the dex cache for resolved methods and
70// fields. However, in the context of the debugger, not all methods and fields are resolved. Since
71// we need to be able to detect possibly inlined method, we pass a null inline method to indicate
72// we don't want to take unresolved methods and fields into account during analysis.
Vladimir Markoe3e02602014-03-12 15:42:41 +000073bool InlineMethodAnalyser::AnalyseMethodCode(verifier::MethodVerifier* verifier,
Vladimir Markobe10e8e2016-01-22 12:09:44 +000074 InlineMethod* result) {
Sebastien Hertz2c87c4d2014-03-21 11:31:51 +010075 DCHECK(verifier != nullptr);
Mathieu Chartiere5f13e52015-02-24 09:37:21 -080076 if (!Runtime::Current()->UseJit()) {
Vladimir Markobe10e8e2016-01-22 12:09:44 +000077 DCHECK_EQ(verifier->CanLoadClasses(), result != nullptr);
Mathieu Chartiere5f13e52015-02-24 09:37:21 -080078 }
Vladimir Markobe10e8e2016-01-22 12:09:44 +000079
80 // Note: verifier->GetMethod() may be null.
81 return AnalyseMethodCode(verifier->CodeItem(),
82 verifier->GetMethodReference(),
83 (verifier->GetAccessFlags() & kAccStatic) != 0u,
84 verifier->GetMethod(),
85 result);
86}
87
88bool InlineMethodAnalyser::AnalyseMethodCode(ArtMethod* method, InlineMethod* result) {
89 const DexFile::CodeItem* code_item = method->GetCodeItem();
90 if (code_item == nullptr) {
91 // Native or abstract.
92 return false;
93 }
94 return AnalyseMethodCode(
95 code_item, method->ToMethodReference(), method->IsStatic(), method, result);
96}
97
98bool InlineMethodAnalyser::AnalyseMethodCode(const DexFile::CodeItem* code_item,
99 const MethodReference& method_ref,
100 bool is_static,
101 ArtMethod* method,
102 InlineMethod* result) {
Vladimir Markoe3e02602014-03-12 15:42:41 +0000103 // We currently support only plain return or 2-instruction methods.
104
Vladimir Markoe3e02602014-03-12 15:42:41 +0000105 DCHECK_NE(code_item->insns_size_in_code_units_, 0u);
106 const Instruction* instruction = Instruction::At(code_item->insns_);
107 Instruction::Code opcode = instruction->Opcode();
108
109 switch (opcode) {
110 case Instruction::RETURN_VOID:
Vladimir Marko9f35ccd2016-02-02 20:12:32 +0000111 if (result != nullptr) {
Vladimir Markobe10e8e2016-01-22 12:09:44 +0000112 result->opcode = kInlineOpNop;
113 result->flags = kInlineSpecial;
114 result->d.data = 0u;
Sebastien Hertz2c87c4d2014-03-21 11:31:51 +0100115 }
Vladimir Markoe3e02602014-03-12 15:42:41 +0000116 return true;
117 case Instruction::RETURN:
118 case Instruction::RETURN_OBJECT:
119 case Instruction::RETURN_WIDE:
Vladimir Markobe10e8e2016-01-22 12:09:44 +0000120 return AnalyseReturnMethod(code_item, result);
Vladimir Markoe3e02602014-03-12 15:42:41 +0000121 case Instruction::CONST:
122 case Instruction::CONST_4:
123 case Instruction::CONST_16:
124 case Instruction::CONST_HIGH16:
125 // TODO: Support wide constants (RETURN_WIDE).
Vladimir Markobe10e8e2016-01-22 12:09:44 +0000126 return AnalyseConstMethod(code_item, result);
Vladimir Markoe3e02602014-03-12 15:42:41 +0000127 case Instruction::IGET:
128 case Instruction::IGET_OBJECT:
129 case Instruction::IGET_BOOLEAN:
130 case Instruction::IGET_BYTE:
131 case Instruction::IGET_CHAR:
132 case Instruction::IGET_SHORT:
133 case Instruction::IGET_WIDE:
Mathieu Chartiere5f13e52015-02-24 09:37:21 -0800134 // TODO: Add handling for JIT.
135 // case Instruction::IGET_QUICK:
136 // case Instruction::IGET_WIDE_QUICK:
137 // case Instruction::IGET_OBJECT_QUICK:
Vladimir Markobe10e8e2016-01-22 12:09:44 +0000138 return AnalyseIGetMethod(code_item, method_ref, is_static, method, result);
Vladimir Markoe3e02602014-03-12 15:42:41 +0000139 case Instruction::IPUT:
140 case Instruction::IPUT_OBJECT:
141 case Instruction::IPUT_BOOLEAN:
142 case Instruction::IPUT_BYTE:
143 case Instruction::IPUT_CHAR:
144 case Instruction::IPUT_SHORT:
145 case Instruction::IPUT_WIDE:
Mathieu Chartiere5f13e52015-02-24 09:37:21 -0800146 // TODO: Add handling for JIT.
147 // case Instruction::IPUT_QUICK:
148 // case Instruction::IPUT_WIDE_QUICK:
149 // case Instruction::IPUT_OBJECT_QUICK:
Vladimir Markobe10e8e2016-01-22 12:09:44 +0000150 return AnalyseIPutMethod(code_item, method_ref, is_static, method, result);
Vladimir Markoe3e02602014-03-12 15:42:41 +0000151 default:
152 return false;
153 }
154}
155
Vladimir Markoc8f60a62014-04-02 15:24:05 +0100156bool InlineMethodAnalyser::IsSyntheticAccessor(MethodReference ref) {
157 const DexFile::MethodId& method_id = ref.dex_file->GetMethodId(ref.dex_method_index);
158 const char* method_name = ref.dex_file->GetMethodName(method_id);
Vladimir Markod5f10052015-05-06 14:09:04 +0100159 // javac names synthetic accessors "access$nnn",
160 // jack names them "-getN", "-putN", "-wrapN".
161 return strncmp(method_name, "access$", strlen("access$")) == 0 ||
162 strncmp(method_name, "-", strlen("-")) == 0;
Vladimir Markoc8f60a62014-04-02 15:24:05 +0100163}
164
Vladimir Markoe3e02602014-03-12 15:42:41 +0000165bool InlineMethodAnalyser::AnalyseReturnMethod(const DexFile::CodeItem* code_item,
166 InlineMethod* result) {
167 const Instruction* return_instruction = Instruction::At(code_item->insns_);
168 Instruction::Code return_opcode = return_instruction->Opcode();
169 uint32_t reg = return_instruction->VRegA_11x();
170 uint32_t arg_start = code_item->registers_size_ - code_item->ins_size_;
171 DCHECK_GE(reg, arg_start);
172 DCHECK_LT((return_opcode == Instruction::RETURN_WIDE) ? reg + 1 : reg,
173 code_item->registers_size_);
174
Sebastien Hertz2c87c4d2014-03-21 11:31:51 +0100175 if (result != nullptr) {
176 result->opcode = kInlineOpReturnArg;
177 result->flags = kInlineSpecial;
178 InlineReturnArgData* data = &result->d.return_data;
179 data->arg = reg - arg_start;
180 data->is_wide = (return_opcode == Instruction::RETURN_WIDE) ? 1u : 0u;
181 data->is_object = (return_opcode == Instruction::RETURN_OBJECT) ? 1u : 0u;
182 data->reserved = 0u;
183 data->reserved2 = 0u;
184 }
Vladimir Markoe3e02602014-03-12 15:42:41 +0000185 return true;
186}
187
188bool InlineMethodAnalyser::AnalyseConstMethod(const DexFile::CodeItem* code_item,
189 InlineMethod* result) {
190 const Instruction* instruction = Instruction::At(code_item->insns_);
191 const Instruction* return_instruction = instruction->Next();
192 Instruction::Code return_opcode = return_instruction->Opcode();
193 if (return_opcode != Instruction::RETURN &&
194 return_opcode != Instruction::RETURN_OBJECT) {
195 return false;
196 }
197
Ian Rogers29a26482014-05-02 15:27:29 -0700198 int32_t return_reg = return_instruction->VRegA_11x();
Vladimir Markoe3e02602014-03-12 15:42:41 +0000199 DCHECK_LT(return_reg, code_item->registers_size_);
200
Ian Rogers29a26482014-05-02 15:27:29 -0700201 int32_t const_value = instruction->VRegB();
Vladimir Markoe3e02602014-03-12 15:42:41 +0000202 if (instruction->Opcode() == Instruction::CONST_HIGH16) {
Ian Rogers29a26482014-05-02 15:27:29 -0700203 const_value <<= 16;
Vladimir Markoe3e02602014-03-12 15:42:41 +0000204 }
Ian Rogers29a26482014-05-02 15:27:29 -0700205 DCHECK_LT(instruction->VRegA(), code_item->registers_size_);
206 if (instruction->VRegA() != return_reg) {
Vladimir Markoe3e02602014-03-12 15:42:41 +0000207 return false; // Not returning the value set by const?
208 }
Ian Rogers29a26482014-05-02 15:27:29 -0700209 if (return_opcode == Instruction::RETURN_OBJECT && const_value != 0) {
Vladimir Markoe3e02602014-03-12 15:42:41 +0000210 return false; // Returning non-null reference constant?
211 }
Sebastien Hertz2c87c4d2014-03-21 11:31:51 +0100212 if (result != nullptr) {
213 result->opcode = kInlineOpNonWideConst;
214 result->flags = kInlineSpecial;
Ian Rogers29a26482014-05-02 15:27:29 -0700215 result->d.data = static_cast<uint64_t>(const_value);
Sebastien Hertz2c87c4d2014-03-21 11:31:51 +0100216 }
Vladimir Markoe3e02602014-03-12 15:42:41 +0000217 return true;
218}
219
Vladimir Markobe10e8e2016-01-22 12:09:44 +0000220bool InlineMethodAnalyser::AnalyseIGetMethod(const DexFile::CodeItem* code_item,
221 const MethodReference& method_ref,
222 bool is_static,
223 ArtMethod* method,
Vladimir Markoe3e02602014-03-12 15:42:41 +0000224 InlineMethod* result) {
Vladimir Markoe3e02602014-03-12 15:42:41 +0000225 const Instruction* instruction = Instruction::At(code_item->insns_);
226 Instruction::Code opcode = instruction->Opcode();
227 DCHECK(IsInstructionIGet(opcode));
228
229 const Instruction* return_instruction = instruction->Next();
230 Instruction::Code return_opcode = return_instruction->Opcode();
231 if (!(return_opcode == Instruction::RETURN_WIDE && opcode == Instruction::IGET_WIDE) &&
232 !(return_opcode == Instruction::RETURN_OBJECT && opcode == Instruction::IGET_OBJECT) &&
233 !(return_opcode == Instruction::RETURN && opcode != Instruction::IGET_WIDE &&
234 opcode != Instruction::IGET_OBJECT)) {
235 return false;
236 }
237
238 uint32_t return_reg = return_instruction->VRegA_11x();
239 DCHECK_LT(return_opcode == Instruction::RETURN_WIDE ? return_reg + 1 : return_reg,
240 code_item->registers_size_);
241
242 uint32_t dst_reg = instruction->VRegA_22c();
243 uint32_t object_reg = instruction->VRegB_22c();
244 uint32_t field_idx = instruction->VRegC_22c();
245 uint32_t arg_start = code_item->registers_size_ - code_item->ins_size_;
246 DCHECK_GE(object_reg, arg_start);
247 DCHECK_LT(object_reg, code_item->registers_size_);
Vladimir Markoe1fced12014-04-04 14:52:53 +0100248 uint32_t object_arg = object_reg - arg_start;
249
Vladimir Markoe3e02602014-03-12 15:42:41 +0000250 DCHECK_LT(opcode == Instruction::IGET_WIDE ? dst_reg + 1 : dst_reg, code_item->registers_size_);
251 if (dst_reg != return_reg) {
252 return false; // Not returning the value retrieved by IGET?
253 }
254
Vladimir Markobe10e8e2016-01-22 12:09:44 +0000255 if (is_static || object_arg != 0u) {
Vladimir Markoc8f60a62014-04-02 15:24:05 +0100256 // TODO: Implement inlining of IGET on non-"this" registers (needs correct stack trace for NPE).
257 // Allow synthetic accessors. We don't care about losing their stack frame in NPE.
Vladimir Markobe10e8e2016-01-22 12:09:44 +0000258 if (!IsSyntheticAccessor(method_ref)) {
Vladimir Markoc8f60a62014-04-02 15:24:05 +0100259 return false;
260 }
Vladimir Markoe3e02602014-03-12 15:42:41 +0000261 }
262
Vladimir Markoe1fced12014-04-04 14:52:53 +0100263 // InlineIGetIPutData::object_arg is only 4 bits wide.
264 static constexpr uint16_t kMaxObjectArg = 15u;
265 if (object_arg > kMaxObjectArg) {
266 return false;
267 }
268
Sebastien Hertz2c87c4d2014-03-21 11:31:51 +0100269 if (result != nullptr) {
270 InlineIGetIPutData* data = &result->d.ifield_data;
Vladimir Markobe10e8e2016-01-22 12:09:44 +0000271 if (!ComputeSpecialAccessorInfo(method, field_idx, false, data)) {
Sebastien Hertz2c87c4d2014-03-21 11:31:51 +0100272 return false;
273 }
274 result->opcode = kInlineOpIGet;
275 result->flags = kInlineSpecial;
276 data->op_variant = IGetVariant(opcode);
Vladimir Markobe10e8e2016-01-22 12:09:44 +0000277 data->method_is_static = is_static ? 1u : 0u;
Vladimir Markoe1fced12014-04-04 14:52:53 +0100278 data->object_arg = object_arg; // Allow IGET on any register, not just "this".
Vladimir Markoc8f60a62014-04-02 15:24:05 +0100279 data->src_arg = 0u;
Vladimir Markoe1fced12014-04-04 14:52:53 +0100280 data->return_arg_plus1 = 0u;
Vladimir Markoe3e02602014-03-12 15:42:41 +0000281 }
Vladimir Markoe3e02602014-03-12 15:42:41 +0000282 return true;
283}
284
Vladimir Markobe10e8e2016-01-22 12:09:44 +0000285bool InlineMethodAnalyser::AnalyseIPutMethod(const DexFile::CodeItem* code_item,
286 const MethodReference& method_ref,
287 bool is_static,
288 ArtMethod* method,
Vladimir Markoe3e02602014-03-12 15:42:41 +0000289 InlineMethod* result) {
Vladimir Markoe3e02602014-03-12 15:42:41 +0000290 const Instruction* instruction = Instruction::At(code_item->insns_);
291 Instruction::Code opcode = instruction->Opcode();
292 DCHECK(IsInstructionIPut(opcode));
293
294 const Instruction* return_instruction = instruction->Next();
295 Instruction::Code return_opcode = return_instruction->Opcode();
Vladimir Markoe1fced12014-04-04 14:52:53 +0100296 uint32_t arg_start = code_item->registers_size_ - code_item->ins_size_;
297 uint16_t return_arg_plus1 = 0u;
Vladimir Markoe3e02602014-03-12 15:42:41 +0000298 if (return_opcode != Instruction::RETURN_VOID) {
Vladimir Markoe1fced12014-04-04 14:52:53 +0100299 if (return_opcode != Instruction::RETURN &&
300 return_opcode != Instruction::RETURN_OBJECT &&
301 return_opcode != Instruction::RETURN_WIDE) {
302 return false;
303 }
304 // Returning an argument.
305 uint32_t return_reg = return_instruction->VRegA_11x();
306 DCHECK_GE(return_reg, arg_start);
307 DCHECK_LT(return_opcode == Instruction::RETURN_WIDE ? return_reg + 1u : return_reg,
308 code_item->registers_size_);
309 return_arg_plus1 = return_reg - arg_start + 1u;
Vladimir Markoe3e02602014-03-12 15:42:41 +0000310 }
311
312 uint32_t src_reg = instruction->VRegA_22c();
313 uint32_t object_reg = instruction->VRegB_22c();
314 uint32_t field_idx = instruction->VRegC_22c();
Vladimir Markoe3e02602014-03-12 15:42:41 +0000315 DCHECK_GE(object_reg, arg_start);
316 DCHECK_LT(object_reg, code_item->registers_size_);
317 DCHECK_GE(src_reg, arg_start);
318 DCHECK_LT(opcode == Instruction::IPUT_WIDE ? src_reg + 1 : src_reg, code_item->registers_size_);
Vladimir Markoe1fced12014-04-04 14:52:53 +0100319 uint32_t object_arg = object_reg - arg_start;
320 uint32_t src_arg = src_reg - arg_start;
Vladimir Markoe3e02602014-03-12 15:42:41 +0000321
Vladimir Markobe10e8e2016-01-22 12:09:44 +0000322 if (is_static || object_arg != 0u) {
Vladimir Markoc8f60a62014-04-02 15:24:05 +0100323 // TODO: Implement inlining of IPUT on non-"this" registers (needs correct stack trace for NPE).
324 // Allow synthetic accessors. We don't care about losing their stack frame in NPE.
Vladimir Markobe10e8e2016-01-22 12:09:44 +0000325 if (!IsSyntheticAccessor(method_ref)) {
Vladimir Markoc8f60a62014-04-02 15:24:05 +0100326 return false;
327 }
Vladimir Markoe3e02602014-03-12 15:42:41 +0000328 }
329
Vladimir Markoe1fced12014-04-04 14:52:53 +0100330 // InlineIGetIPutData::object_arg/src_arg/return_arg_plus1 are each only 4 bits wide.
331 static constexpr uint16_t kMaxObjectArg = 15u;
332 static constexpr uint16_t kMaxSrcArg = 15u;
333 static constexpr uint16_t kMaxReturnArgPlus1 = 15u;
334 if (object_arg > kMaxObjectArg || src_arg > kMaxSrcArg || return_arg_plus1 > kMaxReturnArgPlus1) {
335 return false;
336 }
337
Sebastien Hertz2c87c4d2014-03-21 11:31:51 +0100338 if (result != nullptr) {
339 InlineIGetIPutData* data = &result->d.ifield_data;
Vladimir Markobe10e8e2016-01-22 12:09:44 +0000340 if (!ComputeSpecialAccessorInfo(method, field_idx, true, data)) {
Sebastien Hertz2c87c4d2014-03-21 11:31:51 +0100341 return false;
342 }
343 result->opcode = kInlineOpIPut;
344 result->flags = kInlineSpecial;
345 data->op_variant = IPutVariant(opcode);
Vladimir Markobe10e8e2016-01-22 12:09:44 +0000346 data->method_is_static = is_static ? 1u : 0u;
Vladimir Markoe1fced12014-04-04 14:52:53 +0100347 data->object_arg = object_arg; // Allow IPUT on any register, not just "this".
348 data->src_arg = src_arg;
349 data->return_arg_plus1 = return_arg_plus1;
Vladimir Markoe3e02602014-03-12 15:42:41 +0000350 }
Vladimir Markoe3e02602014-03-12 15:42:41 +0000351 return true;
352}
353
Vladimir Markobe10e8e2016-01-22 12:09:44 +0000354bool InlineMethodAnalyser::ComputeSpecialAccessorInfo(ArtMethod* method,
355 uint32_t field_idx,
356 bool is_put,
Vladimir Markoe3e02602014-03-12 15:42:41 +0000357 InlineIGetIPutData* result) {
Vladimir Markobe10e8e2016-01-22 12:09:44 +0000358 if (method == nullptr) {
359 return false;
360 }
361 mirror::DexCache* dex_cache = method->GetDexCache();
362 size_t pointer_size = Runtime::Current()->GetClassLinker()->GetImagePointerSize();
363 ArtField* field = dex_cache->GetResolvedField(field_idx, pointer_size);
364 if (field == nullptr || field->IsStatic()) {
Vladimir Markoe3e02602014-03-12 15:42:41 +0000365 return false;
366 }
367 mirror::Class* method_class = method->GetDeclaringClass();
368 mirror::Class* field_class = field->GetDeclaringClass();
369 if (!method_class->CanAccessResolvedField(field_class, field, dex_cache, field_idx) ||
370 (is_put && field->IsFinal() && method_class != field_class)) {
371 return false;
372 }
373 DCHECK_GE(field->GetOffset().Int32Value(), 0);
374 result->field_idx = field_idx;
375 result->field_offset = field->GetOffset().Int32Value();
376 result->is_volatile = field->IsVolatile();
377 return true;
378}
379
380} // namespace art