1 /*
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 #ifndef ART_RUNTIME_ART_METHOD_INL_H_
18 #define ART_RUNTIME_ART_METHOD_INL_H_
19
20 #include "art_method.h"
21
22 #include "art_field.h"
23 #include "base/callee_save_type.h"
24 #include "class_linker-inl.h"
25 #include "common_throws.h"
26 #include "dex/code_item_accessors-inl.h"
27 #include "dex/dex_file-inl.h"
28 #include "dex/dex_file_annotations.h"
29 #include "dex/dex_file_types.h"
30 #include "dex/invoke_type.h"
31 #include "dex/primitive.h"
32 #include "dex/signature.h"
33 #include "gc_root-inl.h"
34 #include "imtable-inl.h"
35 #include "intrinsics_enum.h"
36 #include "jit/jit.h"
37 #include "jit/profiling_info.h"
38 #include "mirror/class-inl.h"
39 #include "mirror/dex_cache-inl.h"
40 #include "mirror/object-inl.h"
41 #include "mirror/object_array.h"
42 #include "mirror/string.h"
43 #include "obj_ptr-inl.h"
44 #include "quick/quick_method_frame_info.h"
45 #include "read_barrier-inl.h"
46 #include "runtime-inl.h"
47 #include "thread-current-inl.h"
48
49 namespace art {
50
51 template <ReadBarrierOption kReadBarrierOption>
GetDeclaringClassUnchecked()52 inline ObjPtr<mirror::Class> ArtMethod::GetDeclaringClassUnchecked() {
53 GcRootSource gc_root_source(this);
54 return declaring_class_.Read<kReadBarrierOption>(&gc_root_source);
55 }
56
57 template <ReadBarrierOption kReadBarrierOption>
GetDeclaringClass()58 inline ObjPtr<mirror::Class> ArtMethod::GetDeclaringClass() {
59 ObjPtr<mirror::Class> result = GetDeclaringClassUnchecked<kReadBarrierOption>();
60 if (kIsDebugBuild) {
61 if (!IsRuntimeMethod()) {
62 CHECK(result != nullptr) << this;
63 } else {
64 CHECK(result == nullptr) << this;
65 }
66 }
67 return result;
68 }
69
SetDeclaringClass(ObjPtr<mirror::Class> new_declaring_class)70 inline void ArtMethod::SetDeclaringClass(ObjPtr<mirror::Class> new_declaring_class) {
71 declaring_class_ = GcRoot<mirror::Class>(new_declaring_class);
72 }
73
CASDeclaringClass(ObjPtr<mirror::Class> expected_class,ObjPtr<mirror::Class> desired_class)74 inline bool ArtMethod::CASDeclaringClass(ObjPtr<mirror::Class> expected_class,
75 ObjPtr<mirror::Class> desired_class) {
76 GcRoot<mirror::Class> expected_root(expected_class);
77 GcRoot<mirror::Class> desired_root(desired_class);
78 auto atomic_root_class = reinterpret_cast<Atomic<GcRoot<mirror::Class>>*>(&declaring_class_);
79 return atomic_root_class->CompareAndSetStrongSequentiallyConsistent(expected_root, desired_root);
80 }
81
GetMethodIndex()82 inline uint16_t ArtMethod::GetMethodIndex() {
83 DCHECK(IsRuntimeMethod() || GetDeclaringClass()->IsResolved());
84 return method_index_;
85 }
86
GetMethodIndexDuringLinking()87 inline uint16_t ArtMethod::GetMethodIndexDuringLinking() {
88 return method_index_;
89 }
90
LookupResolvedClassFromTypeIndex(dex::TypeIndex type_idx)91 inline ObjPtr<mirror::Class> ArtMethod::LookupResolvedClassFromTypeIndex(dex::TypeIndex type_idx) {
92 ScopedAssertNoThreadSuspension ants(__FUNCTION__);
93 ObjPtr<mirror::Class> type =
94 Runtime::Current()->GetClassLinker()->LookupResolvedType(type_idx, this);
95 DCHECK(!Thread::Current()->IsExceptionPending());
96 return type;
97 }
98
ResolveClassFromTypeIndex(dex::TypeIndex type_idx)99 inline ObjPtr<mirror::Class> ArtMethod::ResolveClassFromTypeIndex(dex::TypeIndex type_idx) {
100 ObjPtr<mirror::Class> type = Runtime::Current()->GetClassLinker()->ResolveType(type_idx, this);
101 DCHECK_EQ(type == nullptr, Thread::Current()->IsExceptionPending());
102 return type;
103 }
104
IsOverridableByDefaultMethod()105 inline bool ArtMethod::IsOverridableByDefaultMethod() {
106 // It is safe to avoid the read barrier here since the constant interface flag
107 // in the `Class` object is stored before creating the `ArtMethod` and storing
108 // the declaring class reference. See `ReadBarrierOption`.
109 return GetDeclaringClass<kWithoutReadBarrier>()->IsInterface();
110 }
111
CheckIncompatibleClassChange(InvokeType type)112 inline bool ArtMethod::CheckIncompatibleClassChange(InvokeType type) {
113 switch (type) {
114 case kStatic:
115 return !IsStatic();
116 case kDirect:
117 return !IsDirect() || IsStatic();
118 case kVirtual: {
119 // We have an error if we are direct or a non-copied (i.e. not part of a real class) interface
120 // method.
121 ObjPtr<mirror::Class> methods_class = GetDeclaringClass();
122 return IsDirect() || (methods_class->IsInterface() && !IsCopied());
123 }
124 case kSuper:
125 // Constructors and static methods are called with invoke-direct.
126 return IsConstructor() || IsStatic();
127 case kInterface: {
128 ObjPtr<mirror::Class> methods_class = GetDeclaringClass();
129 return IsDirect() || !(methods_class->IsInterface() || methods_class->IsObjectClass());
130 }
131 case kPolymorphic:
132 return !IsSignaturePolymorphic();
133 default:
134 LOG(FATAL) << "Unreachable - invocation type: " << type;
135 UNREACHABLE();
136 }
137 }
138
IsCalleeSaveMethod()139 inline bool ArtMethod::IsCalleeSaveMethod() {
140 if (!IsRuntimeMethod()) {
141 return false;
142 }
143 Runtime* runtime = Runtime::Current();
144 bool result = false;
145 for (uint32_t i = 0; i < static_cast<uint32_t>(CalleeSaveType::kLastCalleeSaveType); i++) {
146 if (this == runtime->GetCalleeSaveMethod(CalleeSaveType(i))) {
147 result = true;
148 break;
149 }
150 }
151 return result;
152 }
153
IsResolutionMethod()154 inline bool ArtMethod::IsResolutionMethod() {
155 bool result = this == Runtime::Current()->GetResolutionMethod();
156 // Check that if we do think it is phony it looks like the resolution method.
157 DCHECK_IMPLIES(result, IsRuntimeMethod());
158 return result;
159 }
160
IsImtUnimplementedMethod()161 inline bool ArtMethod::IsImtUnimplementedMethod() {
162 bool result = this == Runtime::Current()->GetImtUnimplementedMethod();
163 // Check that if we do think it is phony it looks like the imt unimplemented method.
164 DCHECK_IMPLIES(result, IsRuntimeMethod());
165 return result;
166 }
167
GetDexFile()168 inline const DexFile* ArtMethod::GetDexFile() {
169 // It is safe to avoid the read barrier here since the dex file is constant, so if we read the
170 // from-space dex file pointer it will be equal to the to-space copy.
171 return GetDexCache<kWithoutReadBarrier>()->GetDexFile();
172 }
173
GetDeclaringClassDescriptor()174 inline const char* ArtMethod::GetDeclaringClassDescriptor() {
175 uint32_t dex_method_idx = GetDexMethodIndex();
176 if (UNLIKELY(dex_method_idx == dex::kDexNoIndex)) {
177 return "<runtime method>";
178 }
179 DCHECK(!IsProxyMethod());
180 const DexFile* dex_file = GetDexFile();
181 return dex_file->GetMethodDeclaringClassDescriptor(dex_file->GetMethodId(dex_method_idx));
182 }
183
GetShorty()184 inline const char* ArtMethod::GetShorty() {
185 uint32_t unused_length;
186 return GetShorty(&unused_length);
187 }
188
GetShorty(uint32_t * out_length)189 inline const char* ArtMethod::GetShorty(uint32_t* out_length) {
190 DCHECK(!IsProxyMethod());
191 const DexFile* dex_file = GetDexFile();
192 return dex_file->GetMethodShorty(dex_file->GetMethodId(GetDexMethodIndex()), out_length);
193 }
194
GetSignature()195 inline const Signature ArtMethod::GetSignature() {
196 uint32_t dex_method_idx = GetDexMethodIndex();
197 if (dex_method_idx != dex::kDexNoIndex) {
198 DCHECK(!IsProxyMethod());
199 const DexFile* dex_file = GetDexFile();
200 return dex_file->GetMethodSignature(dex_file->GetMethodId(dex_method_idx));
201 }
202 return Signature::NoSignature();
203 }
204
GetName()205 inline const char* ArtMethod::GetName() {
206 uint32_t dex_method_idx = GetDexMethodIndex();
207 if (LIKELY(dex_method_idx != dex::kDexNoIndex)) {
208 DCHECK(!IsProxyMethod());
209 const DexFile* dex_file = GetDexFile();
210 return dex_file->GetMethodName(dex_file->GetMethodId(dex_method_idx));
211 }
212 return GetRuntimeMethodName();
213 }
214
GetNameView()215 inline std::string_view ArtMethod::GetNameView() {
216 uint32_t dex_method_idx = GetDexMethodIndex();
217 if (LIKELY(dex_method_idx != dex::kDexNoIndex)) {
218 DCHECK(!IsProxyMethod());
219 const DexFile* dex_file = GetDexFile();
220 return dex_file->GetMethodNameView(dex_method_idx);
221 }
222 return GetRuntimeMethodName();
223 }
224
ResolveNameString()225 inline ObjPtr<mirror::String> ArtMethod::ResolveNameString() {
226 DCHECK(!IsProxyMethod());
227 const dex::MethodId& method_id = GetDexFile()->GetMethodId(GetDexMethodIndex());
228 return Runtime::Current()->GetClassLinker()->ResolveString(method_id.name_idx_, this);
229 }
230
NameEquals(ObjPtr<mirror::String> name)231 inline bool ArtMethod::NameEquals(ObjPtr<mirror::String> name) {
232 DCHECK(!IsProxyMethod());
233 const DexFile* dex_file = GetDexFile();
234 const dex::MethodId& method_id = dex_file->GetMethodId(GetDexMethodIndex());
235 const dex::StringIndex name_idx = method_id.name_idx_;
236 uint32_t utf16_length;
237 const char* utf8_name = dex_file->StringDataAndUtf16LengthByIdx(name_idx, &utf16_length);
238 return dchecked_integral_cast<uint32_t>(name->GetLength()) == utf16_length &&
239 name->Equals(utf8_name);
240 }
241
GetCodeItem()242 inline const dex::CodeItem* ArtMethod::GetCodeItem() {
243 if (!HasCodeItem()) {
244 return nullptr;
245 }
246 Runtime* runtime = Runtime::Current();
247 PointerSize pointer_size = runtime->GetClassLinker()->GetImagePointerSize();
248 return runtime->IsAotCompiler()
249 ? GetDexFile()->GetCodeItem(reinterpret_cast32<uint32_t>(GetDataPtrSize(pointer_size)))
250 : reinterpret_cast<const dex::CodeItem*>(
251 reinterpret_cast<uintptr_t>(GetDataPtrSize(pointer_size)) & ~1);
252 }
253
IsResolvedTypeIdx(dex::TypeIndex type_idx)254 inline bool ArtMethod::IsResolvedTypeIdx(dex::TypeIndex type_idx) {
255 DCHECK(!IsProxyMethod());
256 return LookupResolvedClassFromTypeIndex(type_idx) != nullptr;
257 }
258
GetLineNumFromDexPC(uint32_t dex_pc)259 inline int32_t ArtMethod::GetLineNumFromDexPC(uint32_t dex_pc) {
260 DCHECK(!IsProxyMethod());
261 if (dex_pc == dex::kDexNoIndex) {
262 return IsNative() ? -2 : -1;
263 }
264 return annotations::GetLineNumFromPC(GetDexFile(), this, dex_pc);
265 }
266
GetPrototype()267 inline const dex::ProtoId& ArtMethod::GetPrototype() {
268 DCHECK(!IsProxyMethod());
269 const DexFile* dex_file = GetDexFile();
270 return dex_file->GetMethodPrototype(dex_file->GetMethodId(GetDexMethodIndex()));
271 }
272
GetParameterTypeList()273 inline const dex::TypeList* ArtMethod::GetParameterTypeList() {
274 DCHECK(!IsProxyMethod());
275 const DexFile* dex_file = GetDexFile();
276 const dex::ProtoId& proto = dex_file->GetMethodPrototype(
277 dex_file->GetMethodId(GetDexMethodIndex()));
278 return dex_file->GetProtoParameters(proto);
279 }
280
GetDeclaringClassSourceFile()281 inline const char* ArtMethod::GetDeclaringClassSourceFile() {
282 DCHECK(!IsProxyMethod());
283 return GetDeclaringClass()->GetSourceFile();
284 }
285
GetClassDefIndex()286 inline uint16_t ArtMethod::GetClassDefIndex() {
287 DCHECK(!IsProxyMethod());
288 if (LIKELY(!IsObsolete())) {
289 return GetDeclaringClass()->GetDexClassDefIndex();
290 } else {
291 return FindObsoleteDexClassDefIndex();
292 }
293 }
294
GetClassDef()295 inline const dex::ClassDef& ArtMethod::GetClassDef() {
296 DCHECK(!IsProxyMethod());
297 return GetDexFile()->GetClassDef(GetClassDefIndex());
298 }
299
GetNumberOfParameters()300 inline size_t ArtMethod::GetNumberOfParameters() {
301 constexpr size_t return_type_count = 1u;
302 uint32_t shorty_length;
303 GetShorty(&shorty_length);
304 return shorty_length - return_type_count;
305 }
306
GetReturnTypeDescriptor()307 inline const char* ArtMethod::GetReturnTypeDescriptor() {
308 DCHECK(!IsProxyMethod());
309 const DexFile* dex_file = GetDexFile();
310 return dex_file->GetTypeDescriptor(dex_file->GetTypeId(GetReturnTypeIndex()));
311 }
312
GetReturnTypePrimitive()313 inline Primitive::Type ArtMethod::GetReturnTypePrimitive() {
314 return Primitive::GetType(GetReturnTypeDescriptor()[0]);
315 }
316
GetTypeDescriptorFromTypeIdx(dex::TypeIndex type_idx)317 inline const char* ArtMethod::GetTypeDescriptorFromTypeIdx(dex::TypeIndex type_idx) {
318 DCHECK(!IsProxyMethod());
319 const DexFile* dex_file = GetDexFile();
320 return dex_file->GetTypeDescriptor(dex_file->GetTypeId(type_idx));
321 }
322
GetClassLoader()323 inline ObjPtr<mirror::ClassLoader> ArtMethod::GetClassLoader() {
324 DCHECK(!IsProxyMethod());
325 return GetDeclaringClass()->GetClassLoader();
326 }
327
328 template <ReadBarrierOption kReadBarrierOption>
GetDexCache()329 inline ObjPtr<mirror::DexCache> ArtMethod::GetDexCache() {
330 if (LIKELY(!IsObsolete())) {
331 ObjPtr<mirror::Class> klass = GetDeclaringClass<kReadBarrierOption>();
332 return klass->GetDexCache<kDefaultVerifyFlags, kReadBarrierOption>();
333 } else {
334 DCHECK(!IsProxyMethod());
335 return GetObsoleteDexCache();
336 }
337 }
338
IsProxyMethod()339 inline bool ArtMethod::IsProxyMethod() {
340 DCHECK(!IsRuntimeMethod()) << "ArtMethod::IsProxyMethod called on a runtime method";
341 // No read barrier needed, we're reading the constant declaring class only to read
342 // the constant proxy flag. See ReadBarrierOption.
343 return GetDeclaringClass<kWithoutReadBarrier>()->IsProxyClass();
344 }
345
GetInterfaceMethodForProxyUnchecked(PointerSize pointer_size)346 inline ArtMethod* ArtMethod::GetInterfaceMethodForProxyUnchecked(PointerSize pointer_size) {
347 DCHECK(IsProxyMethod());
348 // Do not check IsAssignableFrom() here as it relies on raw reference comparison
349 // which may give false negatives while visiting references for a non-CC moving GC.
350 return reinterpret_cast<ArtMethod*>(GetDataPtrSize(pointer_size));
351 }
352
GetInterfaceMethodIfProxy(PointerSize pointer_size)353 inline ArtMethod* ArtMethod::GetInterfaceMethodIfProxy(PointerSize pointer_size) {
354 if (LIKELY(!IsProxyMethod())) {
355 return this;
356 }
357 ArtMethod* interface_method = GetInterfaceMethodForProxyUnchecked(pointer_size);
358 // We can check that the proxy class implements the interface only if the proxy class
359 // is resolved, otherwise the interface table is not yet initialized.
360 DCHECK_IMPLIES(GetDeclaringClass()->IsResolved(),
361 interface_method->GetDeclaringClass()->IsAssignableFrom(GetDeclaringClass()));
362 return interface_method;
363 }
364
GetReturnTypeIndex()365 inline dex::TypeIndex ArtMethod::GetReturnTypeIndex() {
366 DCHECK(!IsProxyMethod());
367 const DexFile* dex_file = GetDexFile();
368 const dex::MethodId& method_id = dex_file->GetMethodId(GetDexMethodIndex());
369 const dex::ProtoId& proto_id = dex_file->GetMethodPrototype(method_id);
370 return proto_id.return_type_idx_;
371 }
372
LookupResolvedReturnType()373 inline ObjPtr<mirror::Class> ArtMethod::LookupResolvedReturnType() {
374 return LookupResolvedClassFromTypeIndex(GetReturnTypeIndex());
375 }
376
ResolveReturnType()377 inline ObjPtr<mirror::Class> ArtMethod::ResolveReturnType() {
378 return ResolveClassFromTypeIndex(GetReturnTypeIndex());
379 }
380
381 template <ReadBarrierOption kReadBarrierOption>
HasSingleImplementation()382 inline bool ArtMethod::HasSingleImplementation() {
383 if (IsFinal() || GetDeclaringClass<kReadBarrierOption>()->IsFinal()) {
384 // We don't set kAccSingleImplementation for these cases since intrinsic
385 // can use the flag also.
386 return true;
387 }
388 return (GetAccessFlags() & kAccSingleImplementation) != 0;
389 }
390
391 template<ReadBarrierOption kReadBarrierOption, typename RootVisitorType>
VisitRoots(RootVisitorType & visitor,PointerSize pointer_size)392 void ArtMethod::VisitRoots(RootVisitorType& visitor, PointerSize pointer_size) {
393 if (LIKELY(!declaring_class_.IsNull())) {
394 visitor.VisitRoot(declaring_class_.AddressWithoutBarrier());
395 ObjPtr<mirror::Class> klass = declaring_class_.Read<kReadBarrierOption>();
396 if (UNLIKELY(klass->IsProxyClass())) {
397 // For normal methods, dex cache shortcuts will be visited through the declaring class.
398 // However, for proxies we need to keep the interface method alive, so we visit its roots.
399 ArtMethod* interface_method = GetInterfaceMethodForProxyUnchecked(pointer_size);
400 DCHECK(interface_method != nullptr);
401 interface_method->VisitRoots<kReadBarrierOption>(visitor, pointer_size);
402 }
403 }
404 }
405
406 template <typename Visitor>
UpdateEntrypoints(const Visitor & visitor,PointerSize pointer_size)407 inline void ArtMethod::UpdateEntrypoints(const Visitor& visitor, PointerSize pointer_size) {
408 if (IsNative()) {
409 const void* old_native_code = GetEntryPointFromJniPtrSize(pointer_size);
410 const void* new_native_code = visitor(old_native_code);
411 if (old_native_code != new_native_code) {
412 SetEntryPointFromJniPtrSize(new_native_code, pointer_size);
413 }
414 }
415 const void* old_code = GetEntryPointFromQuickCompiledCodePtrSize(pointer_size);
416 const void* new_code = visitor(old_code);
417 if (old_code != new_code) {
418 SetEntryPointFromQuickCompiledCodePtrSize(new_code, pointer_size);
419 }
420 }
421
DexInstructions()422 inline CodeItemInstructionAccessor ArtMethod::DexInstructions() {
423 return CodeItemInstructionAccessor(*GetDexFile(), GetCodeItem());
424 }
425
DexInstructionData()426 inline CodeItemDataAccessor ArtMethod::DexInstructionData() {
427 return CodeItemDataAccessor(*GetDexFile(), GetCodeItem());
428 }
429
DexInstructionDebugInfo()430 inline CodeItemDebugInfoAccessor ArtMethod::DexInstructionDebugInfo() {
431 return CodeItemDebugInfoAccessor(*GetDexFile(), GetCodeItem(), GetDexMethodIndex());
432 }
433
CounterHasChanged(uint16_t threshold)434 inline bool ArtMethod::CounterHasChanged(uint16_t threshold) {
435 DCHECK(!IsAbstract());
436 DCHECK_EQ(threshold, Runtime::Current()->GetJITOptions()->GetWarmupThreshold());
437 return hotness_count_ != threshold;
438 }
439
ResetCounter(uint16_t new_value)440 inline void ArtMethod::ResetCounter(uint16_t new_value) {
441 if (IsAbstract()) {
442 return;
443 }
444 if (IsMemorySharedMethod()) {
445 return;
446 }
447 DCHECK_EQ(new_value, Runtime::Current()->GetJITOptions()->GetWarmupThreshold());
448 // Avoid dirtying the value if possible.
449 if (hotness_count_ != new_value) {
450 hotness_count_ = new_value;
451 }
452 }
453
SetHotCounter()454 inline void ArtMethod::SetHotCounter() {
455 DCHECK(!IsAbstract());
456 // Avoid dirtying the value if possible.
457 if (hotness_count_ != 0) {
458 hotness_count_ = 0;
459 }
460 }
461
UpdateCounter(int32_t new_samples)462 inline void ArtMethod::UpdateCounter(int32_t new_samples) {
463 DCHECK(!IsAbstract());
464 DCHECK_GT(new_samples, 0);
465 DCHECK_LE(new_samples, std::numeric_limits<uint16_t>::max());
466 if (IsMemorySharedMethod()) {
467 return;
468 }
469 uint16_t old_hotness_count = hotness_count_;
470 uint16_t new_count = (old_hotness_count <= new_samples) ? 0u : old_hotness_count - new_samples;
471 // Avoid dirtying the value if possible.
472 if (old_hotness_count != new_count) {
473 hotness_count_ = new_count;
474 }
475 }
476
CounterIsHot()477 inline bool ArtMethod::CounterIsHot() {
478 DCHECK(!IsAbstract());
479 return hotness_count_ == 0;
480 }
481
CounterHasReached(uint16_t samples,uint16_t threshold)482 inline bool ArtMethod::CounterHasReached(uint16_t samples, uint16_t threshold) {
483 DCHECK(!IsAbstract());
484 DCHECK_EQ(threshold, Runtime::Current()->GetJITOptions()->GetWarmupThreshold());
485 DCHECK_LE(samples, threshold);
486 return hotness_count_ <= (threshold - samples);
487 }
488
GetCounter()489 inline uint16_t ArtMethod::GetCounter() {
490 DCHECK(!IsAbstract());
491 return hotness_count_;
492 }
493
GetImtIndex()494 inline uint32_t ArtMethod::GetImtIndex() {
495 if (LIKELY(IsAbstract())) {
496 return imt_index_;
497 } else {
498 return ImTable::GetImtIndex(this);
499 }
500 }
501
CalculateAndSetImtIndex()502 inline void ArtMethod::CalculateAndSetImtIndex() {
503 DCHECK(IsAbstract()) << PrettyMethod();
504 imt_index_ = ImTable::GetImtIndex(this);
505 }
506
507 } // namespace art
508
509 #endif // ART_RUNTIME_ART_METHOD_INL_H_
510