blob: 046d2257f4dd9d9e739f0b7326a93d43b93cc8e6 [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#ifndef ART_RUNTIME_QUICK_INLINE_METHOD_ANALYSER_H_
18#define ART_RUNTIME_QUICK_INLINE_METHOD_ANALYSER_H_
19
20#include "base/macros.h"
21#include "base/mutex.h"
22#include "dex_file.h"
23#include "dex_instruction.h"
Vladimir Markoc8f60a62014-04-02 15:24:05 +010024#include "method_reference.h"
Vladimir Markoe3e02602014-03-12 15:42:41 +000025
26/*
27 * NOTE: This code is part of the quick compiler. It lives in the runtime
28 * only to allow the debugger to check whether a method has been inlined.
29 */
30
31namespace art {
32
33namespace verifier {
34class MethodVerifier;
35} // namespace verifier
36
37enum InlineMethodOpcode : uint16_t {
38 kIntrinsicDoubleCvt,
39 kIntrinsicFloatCvt,
Aart Bik59c94542016-01-25 14:20:58 -080040 kIntrinsicFloatIsInfinite,
41 kIntrinsicDoubleIsInfinite,
42 kIntrinsicFloatIsNaN,
43 kIntrinsicDoubleIsNaN,
Serban Constantinescu23abec92014-07-02 16:13:38 +010044 kIntrinsicReverseBits,
Vladimir Markoe3e02602014-03-12 15:42:41 +000045 kIntrinsicReverseBytes,
Aart Bik3f67e692016-01-15 14:35:12 -080046 kIntrinsicBitCount,
Aart Bik59c94542016-01-25 14:20:58 -080047 kIntrinsicCompare,
48 kIntrinsicHighestOneBit,
49 kIntrinsicLowestOneBit,
Scott Wakeling611d3392015-07-10 11:42:06 +010050 kIntrinsicNumberOfLeadingZeros,
Scott Wakeling9ee23f42015-07-23 10:44:35 +010051 kIntrinsicNumberOfTrailingZeros,
52 kIntrinsicRotateRight,
53 kIntrinsicRotateLeft,
Aart Bik59c94542016-01-25 14:20:58 -080054 kIntrinsicSignum,
Vladimir Markoe3e02602014-03-12 15:42:41 +000055 kIntrinsicAbsInt,
56 kIntrinsicAbsLong,
57 kIntrinsicAbsFloat,
58 kIntrinsicAbsDouble,
59 kIntrinsicMinMaxInt,
Serban Constantinescu23abec92014-07-02 16:13:38 +010060 kIntrinsicMinMaxLong,
61 kIntrinsicMinMaxFloat,
62 kIntrinsicMinMaxDouble,
Mark Mendella4f12202015-08-06 15:23:34 -040063 kIntrinsicCos,
64 kIntrinsicSin,
65 kIntrinsicAcos,
66 kIntrinsicAsin,
67 kIntrinsicAtan,
68 kIntrinsicAtan2,
69 kIntrinsicCbrt,
70 kIntrinsicCosh,
71 kIntrinsicExp,
72 kIntrinsicExpm1,
73 kIntrinsicHypot,
74 kIntrinsicLog,
75 kIntrinsicLog10,
76 kIntrinsicNextAfter,
77 kIntrinsicSinh,
78 kIntrinsicTan,
79 kIntrinsicTanh,
Vladimir Markoe3e02602014-03-12 15:42:41 +000080 kIntrinsicSqrt,
Serban Constantinescu2eba1fa2014-07-31 19:07:17 +010081 kIntrinsicCeil,
82 kIntrinsicFloor,
83 kIntrinsicRint,
84 kIntrinsicRoundFloat,
85 kIntrinsicRoundDouble,
Mathieu Chartiercd48f2d2014-09-09 13:51:09 -070086 kIntrinsicReferenceGetReferent,
Vladimir Markoe3e02602014-03-12 15:42:41 +000087 kIntrinsicCharAt,
88 kIntrinsicCompareTo,
agicsaki7da072f2015-08-12 20:30:17 -070089 kIntrinsicEquals,
Jeff Hao848f70a2014-01-15 13:49:50 -080090 kIntrinsicGetCharsNoCheck,
Vladimir Markoe3e02602014-03-12 15:42:41 +000091 kIntrinsicIsEmptyOrLength,
92 kIntrinsicIndexOf,
Jeff Hao848f70a2014-01-15 13:49:50 -080093 kIntrinsicNewStringFromBytes,
94 kIntrinsicNewStringFromChars,
95 kIntrinsicNewStringFromString,
Vladimir Markoe3e02602014-03-12 15:42:41 +000096 kIntrinsicCurrentThread,
97 kIntrinsicPeek,
98 kIntrinsicPoke,
99 kIntrinsicCas,
100 kIntrinsicUnsafeGet,
101 kIntrinsicUnsafePut,
DaniilSokolov70c4f062014-06-24 17:34:00 -0700102 kIntrinsicSystemArrayCopyCharArray,
Nicolas Geoffrayee3cf072015-10-06 11:45:02 +0100103 kIntrinsicSystemArrayCopy,
Vladimir Markoe3e02602014-03-12 15:42:41 +0000104
105 kInlineOpNop,
106 kInlineOpReturnArg,
107 kInlineOpNonWideConst,
108 kInlineOpIGet,
109 kInlineOpIPut,
Jeff Hao848f70a2014-01-15 13:49:50 -0800110 kInlineStringInit,
Vladimir Markoe3e02602014-03-12 15:42:41 +0000111};
112std::ostream& operator<<(std::ostream& os, const InlineMethodOpcode& rhs);
113
114enum InlineMethodFlags : uint16_t {
115 kNoInlineMethodFlags = 0x0000,
116 kInlineIntrinsic = 0x0001,
117 kInlineSpecial = 0x0002,
118};
119
120// IntrinsicFlags are stored in InlineMethod::d::raw_data
121enum IntrinsicFlags {
122 kIntrinsicFlagNone = 0,
123
124 // kIntrinsicMinMaxInt
125 kIntrinsicFlagMax = kIntrinsicFlagNone,
126 kIntrinsicFlagMin = 1,
127
128 // kIntrinsicIsEmptyOrLength
129 kIntrinsicFlagLength = kIntrinsicFlagNone,
130 kIntrinsicFlagIsEmpty = kIntrinsicFlagMin,
131
132 // kIntrinsicIndexOf
133 kIntrinsicFlagBase0 = kIntrinsicFlagMin,
134
135 // kIntrinsicUnsafeGet, kIntrinsicUnsafePut, kIntrinsicUnsafeCas
136 kIntrinsicFlagIsLong = kIntrinsicFlagMin,
137 // kIntrinsicUnsafeGet, kIntrinsicUnsafePut
138 kIntrinsicFlagIsVolatile = 2,
139 // kIntrinsicUnsafePut, kIntrinsicUnsafeCas
140 kIntrinsicFlagIsObject = 4,
141 // kIntrinsicUnsafePut
142 kIntrinsicFlagIsOrdered = 8,
Andreas Gampe71fb52f2014-12-29 17:43:08 -0800143
144 // kIntrinsicDoubleCvt, kIntrinsicFloatCvt.
145 kIntrinsicFlagToFloatingPoint = kIntrinsicFlagMin,
Vladimir Markoe3e02602014-03-12 15:42:41 +0000146};
147
148struct InlineIGetIPutData {
Vladimir Markoaf6925b2014-10-31 16:37:32 +0000149 // The op_variant below is DexMemAccessType but the runtime doesn't know that enumeration.
Vladimir Markoe3e02602014-03-12 15:42:41 +0000150 uint16_t op_variant : 3;
Vladimir Markoe1fced12014-04-04 14:52:53 +0100151 uint16_t method_is_static : 1;
Vladimir Markoe3e02602014-03-12 15:42:41 +0000152 uint16_t object_arg : 4;
153 uint16_t src_arg : 4; // iput only
Vladimir Markoe1fced12014-04-04 14:52:53 +0100154 uint16_t return_arg_plus1 : 4; // iput only, method argument to return + 1, 0 = return void.
Vladimir Markoe3e02602014-03-12 15:42:41 +0000155 uint16_t field_idx;
156 uint32_t is_volatile : 1;
157 uint32_t field_offset : 31;
158};
Andreas Gampe575e78c2014-11-03 23:41:03 -0800159static_assert(sizeof(InlineIGetIPutData) == sizeof(uint64_t), "Invalid size of InlineIGetIPutData");
Vladimir Markoe3e02602014-03-12 15:42:41 +0000160
161struct InlineReturnArgData {
162 uint16_t arg;
163 uint16_t is_wide : 1;
164 uint16_t is_object : 1;
165 uint16_t reserved : 14;
166 uint32_t reserved2;
167};
Andreas Gampe575e78c2014-11-03 23:41:03 -0800168static_assert(sizeof(InlineReturnArgData) == sizeof(uint64_t),
169 "Invalid size of InlineReturnArgData");
Vladimir Markoe3e02602014-03-12 15:42:41 +0000170
171struct InlineMethod {
172 InlineMethodOpcode opcode;
173 InlineMethodFlags flags;
174 union {
175 uint64_t data;
176 InlineIGetIPutData ifield_data;
177 InlineReturnArgData return_data;
178 } d;
179};
180
181class InlineMethodAnalyser {
182 public:
183 /**
184 * Analyse method code to determine if the method is a candidate for inlining.
185 * If it is, record the inlining data.
186 *
187 * @param verifier the method verifier holding data about the method to analyse.
188 * @param method placeholder for the inline method data.
189 * @return true if the method is a candidate for inlining, false otherwise.
190 */
Vladimir Markobe10e8e2016-01-22 12:09:44 +0000191 static bool AnalyseMethodCode(verifier::MethodVerifier* verifier, InlineMethod* result)
192 SHARED_REQUIRES(Locks::mutator_lock_);
193 static bool AnalyseMethodCode(ArtMethod* method, InlineMethod* result)
Mathieu Chartier90443472015-07-16 20:32:27 -0700194 SHARED_REQUIRES(Locks::mutator_lock_);
Vladimir Markoe3e02602014-03-12 15:42:41 +0000195
196 static constexpr bool IsInstructionIGet(Instruction::Code opcode) {
197 return Instruction::IGET <= opcode && opcode <= Instruction::IGET_SHORT;
198 }
199
200 static constexpr bool IsInstructionIPut(Instruction::Code opcode) {
201 return Instruction::IPUT <= opcode && opcode <= Instruction::IPUT_SHORT;
202 }
203
204 static constexpr uint16_t IGetVariant(Instruction::Code opcode) {
205 return opcode - Instruction::IGET;
206 }
207
208 static constexpr uint16_t IPutVariant(Instruction::Code opcode) {
209 return opcode - Instruction::IPUT;
210 }
211
Vladimir Markoc8f60a62014-04-02 15:24:05 +0100212 // Determines whether the method is a synthetic accessor (method name starts with "access$").
213 static bool IsSyntheticAccessor(MethodReference ref);
214
Vladimir Markoe3e02602014-03-12 15:42:41 +0000215 private:
Vladimir Markobe10e8e2016-01-22 12:09:44 +0000216 static bool AnalyseMethodCode(const DexFile::CodeItem* code_item,
217 const MethodReference& method_ref,
218 bool is_static,
219 ArtMethod* method,
220 InlineMethod* result)
221 SHARED_REQUIRES(Locks::mutator_lock_);
Vladimir Markoe3e02602014-03-12 15:42:41 +0000222 static bool AnalyseReturnMethod(const DexFile::CodeItem* code_item, InlineMethod* result);
223 static bool AnalyseConstMethod(const DexFile::CodeItem* code_item, InlineMethod* result);
Vladimir Markobe10e8e2016-01-22 12:09:44 +0000224 static bool AnalyseIGetMethod(const DexFile::CodeItem* code_item,
225 const MethodReference& method_ref,
226 bool is_static,
227 ArtMethod* method,
228 InlineMethod* result)
Mathieu Chartier90443472015-07-16 20:32:27 -0700229 SHARED_REQUIRES(Locks::mutator_lock_);
Vladimir Markobe10e8e2016-01-22 12:09:44 +0000230 static bool AnalyseIPutMethod(const DexFile::CodeItem* code_item,
231 const MethodReference& method_ref,
232 bool is_static,
233 ArtMethod* method,
234 InlineMethod* result)
Mathieu Chartier90443472015-07-16 20:32:27 -0700235 SHARED_REQUIRES(Locks::mutator_lock_);
Vladimir Markoe3e02602014-03-12 15:42:41 +0000236
237 // Can we fast path instance field access in a verified accessor?
238 // If yes, computes field's offset and volatility and whether the method is static or not.
Vladimir Markobe10e8e2016-01-22 12:09:44 +0000239 static bool ComputeSpecialAccessorInfo(ArtMethod* method,
240 uint32_t field_idx,
241 bool is_put,
Vladimir Markoe3e02602014-03-12 15:42:41 +0000242 InlineIGetIPutData* result)
Mathieu Chartier90443472015-07-16 20:32:27 -0700243 SHARED_REQUIRES(Locks::mutator_lock_);
Vladimir Markoe3e02602014-03-12 15:42:41 +0000244};
245
246} // namespace art
247
248#endif // ART_RUNTIME_QUICK_INLINE_METHOD_ANALYSER_H_