1 /* 2 * Copyright (C) 2012 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_COMPILER_DRIVER_COMPILER_DRIVER_INL_H_ 18 #define ART_COMPILER_DRIVER_COMPILER_DRIVER_INL_H_ 19 20 #include "compiler_driver.h" 21 22 #include "art_field-inl.h" 23 #include "art_method-inl.h" 24 #include "class_linker-inl.h" 25 #include "dex_compilation_unit.h" 26 #include "mirror/class_loader.h" 27 #include "mirror/dex_cache-inl.h" 28 #include "scoped_thread_state_change.h" 29 #include "handle_scope-inl.h" 30 31 namespace art { 32 33 inline mirror::DexCache* CompilerDriver::GetDexCache(const DexCompilationUnit* mUnit) { 34 return mUnit->GetClassLinker()->FindDexCache(Thread::Current(), *mUnit->GetDexFile(), false); 35 } 36 37 inline mirror::ClassLoader* CompilerDriver::GetClassLoader(const ScopedObjectAccess& soa, 38 const DexCompilationUnit* mUnit) { 39 return soa.Decode<mirror::ClassLoader*>(mUnit->GetClassLoader()); 40 } 41 42 inline mirror::Class* CompilerDriver::ResolveClass( 43 const ScopedObjectAccess& soa, Handle<mirror::DexCache> dex_cache, 44 Handle<mirror::ClassLoader> class_loader, uint16_t cls_index, 45 const DexCompilationUnit* mUnit) { 46 DCHECK_EQ(dex_cache->GetDexFile(), mUnit->GetDexFile()); 47 DCHECK_EQ(class_loader.Get(), soa.Decode<mirror::ClassLoader*>(mUnit->GetClassLoader())); 48 mirror::Class* cls = mUnit->GetClassLinker()->ResolveType( 49 *mUnit->GetDexFile(), cls_index, dex_cache, class_loader); 50 DCHECK_EQ(cls == nullptr, soa.Self()->IsExceptionPending()); 51 if (UNLIKELY(cls == nullptr)) { 52 // Clean up any exception left by type resolution. 53 soa.Self()->ClearException(); 54 } 55 return cls; 56 } 57 58 inline mirror::Class* CompilerDriver::ResolveCompilingMethodsClass( 59 const ScopedObjectAccess& soa, Handle<mirror::DexCache> dex_cache, 60 Handle<mirror::ClassLoader> class_loader, const DexCompilationUnit* mUnit) { 61 DCHECK_EQ(dex_cache->GetDexFile(), mUnit->GetDexFile()); 62 DCHECK_EQ(class_loader.Get(), soa.Decode<mirror::ClassLoader*>(mUnit->GetClassLoader())); 63 const DexFile::MethodId& referrer_method_id = 64 mUnit->GetDexFile()->GetMethodId(mUnit->GetDexMethodIndex()); 65 return ResolveClass(soa, dex_cache, class_loader, referrer_method_id.class_idx_, mUnit); 66 } 67 68 inline ArtField* CompilerDriver::ResolveFieldWithDexFile( 69 const ScopedObjectAccess& soa, Handle<mirror::DexCache> dex_cache, 70 Handle<mirror::ClassLoader> class_loader, const DexFile* dex_file, 71 uint32_t field_idx, bool is_static) { 72 DCHECK_EQ(dex_cache->GetDexFile(), dex_file); 73 ArtField* resolved_field = Runtime::Current()->GetClassLinker()->ResolveField( 74 *dex_file, field_idx, dex_cache, class_loader, is_static); 75 DCHECK_EQ(resolved_field == nullptr, soa.Self()->IsExceptionPending()); 76 if (UNLIKELY(resolved_field == nullptr)) { 77 // Clean up any exception left by type resolution. 78 soa.Self()->ClearException(); 79 return nullptr; 80 } 81 if (UNLIKELY(resolved_field->IsStatic() != is_static)) { 82 // ClassLinker can return a field of the wrong kind directly from the DexCache. 83 // Silently return null on such incompatible class change. 84 return nullptr; 85 } 86 return resolved_field; 87 } 88 89 inline mirror::DexCache* CompilerDriver::FindDexCache(const DexFile* dex_file) { 90 return Runtime::Current()->GetClassLinker()->FindDexCache(Thread::Current(), *dex_file, false); 91 } 92 93 inline ArtField* CompilerDriver::ResolveField( 94 const ScopedObjectAccess& soa, Handle<mirror::DexCache> dex_cache, 95 Handle<mirror::ClassLoader> class_loader, const DexCompilationUnit* mUnit, 96 uint32_t field_idx, bool is_static) { 97 DCHECK_EQ(class_loader.Get(), soa.Decode<mirror::ClassLoader*>(mUnit->GetClassLoader())); 98 return ResolveFieldWithDexFile(soa, dex_cache, class_loader, mUnit->GetDexFile(), field_idx, 99 is_static); 100 } 101 102 inline void CompilerDriver::GetResolvedFieldDexFileLocation( 103 ArtField* resolved_field, const DexFile** declaring_dex_file, 104 uint16_t* declaring_class_idx, uint16_t* declaring_field_idx) { 105 mirror::Class* declaring_class = resolved_field->GetDeclaringClass(); 106 *declaring_dex_file = declaring_class->GetDexCache()->GetDexFile(); 107 *declaring_class_idx = declaring_class->GetDexTypeIndex(); 108 *declaring_field_idx = resolved_field->GetDexFieldIndex(); 109 } 110 111 inline bool CompilerDriver::IsFieldVolatile(ArtField* field) { 112 return field->IsVolatile(); 113 } 114 115 inline MemberOffset CompilerDriver::GetFieldOffset(ArtField* field) { 116 return field->GetOffset(); 117 } 118 119 inline std::pair<bool, bool> CompilerDriver::IsFastInstanceField( 120 mirror::DexCache* dex_cache, mirror::Class* referrer_class, 121 ArtField* resolved_field, uint16_t field_idx) { 122 DCHECK(!resolved_field->IsStatic()); 123 mirror::Class* fields_class = resolved_field->GetDeclaringClass(); 124 bool fast_get = referrer_class != nullptr && 125 referrer_class->CanAccessResolvedField(fields_class, resolved_field, 126 dex_cache, field_idx); 127 bool fast_put = fast_get && (!resolved_field->IsFinal() || fields_class == referrer_class); 128 return std::make_pair(fast_get, fast_put); 129 } 130 131 template <typename ArtMember> 132 inline bool CompilerDriver::CanAccessResolvedMember(mirror::Class* referrer_class ATTRIBUTE_UNUSED, 133 mirror::Class* access_to ATTRIBUTE_UNUSED, 134 ArtMember* member ATTRIBUTE_UNUSED, 135 mirror::DexCache* dex_cache ATTRIBUTE_UNUSED, 136 uint32_t field_idx ATTRIBUTE_UNUSED) { 137 // Not defined for ArtMember values other than ArtField or ArtMethod. 138 UNREACHABLE(); 139 } 140 141 template <> 142 inline bool CompilerDriver::CanAccessResolvedMember<ArtField>(mirror::Class* referrer_class, 143 mirror::Class* access_to, 144 ArtField* field, 145 mirror::DexCache* dex_cache, 146 uint32_t field_idx) { 147 return referrer_class->CanAccessResolvedField(access_to, field, dex_cache, field_idx); 148 } 149 150 template <> 151 inline bool CompilerDriver::CanAccessResolvedMember<ArtMethod>( 152 mirror::Class* referrer_class, 153 mirror::Class* access_to, 154 ArtMethod* method, 155 mirror::DexCache* dex_cache, 156 uint32_t field_idx) { 157 return referrer_class->CanAccessResolvedMethod(access_to, method, dex_cache, field_idx); 158 } 159 160 template <typename ArtMember> 161 inline std::pair<bool, bool> CompilerDriver::IsClassOfStaticMemberAvailableToReferrer( 162 mirror::DexCache* dex_cache, 163 mirror::Class* referrer_class, 164 ArtMember* resolved_member, 165 uint16_t member_idx, 166 uint32_t* storage_index) { 167 DCHECK(resolved_member->IsStatic()); 168 if (LIKELY(referrer_class != nullptr)) { 169 mirror::Class* members_class = resolved_member->GetDeclaringClass(); 170 if (members_class == referrer_class) { 171 *storage_index = members_class->GetDexTypeIndex(); 172 return std::make_pair(true, true); 173 } 174 if (CanAccessResolvedMember<ArtMember>( 175 referrer_class, members_class, resolved_member, dex_cache, member_idx)) { 176 // We have the resolved member, we must make it into a index for the referrer 177 // in its static storage (which may fail if it doesn't have a slot for it) 178 // TODO: for images we can elide the static storage base null check 179 // if we know there's a non-null entry in the image 180 const DexFile* dex_file = dex_cache->GetDexFile(); 181 uint32_t storage_idx = DexFile::kDexNoIndex; 182 if (LIKELY(members_class->GetDexCache() == dex_cache)) { 183 // common case where the dex cache of both the referrer and the member are the same, 184 // no need to search the dex file 185 storage_idx = members_class->GetDexTypeIndex(); 186 } else { 187 // Search dex file for localized ssb index, may fail if member's class is a parent 188 // of the class mentioned in the dex file and there is no dex cache entry. 189 storage_idx = resolved_member->GetDeclaringClass()->FindTypeIndexInOtherDexFile(*dex_file); 190 } 191 if (storage_idx != DexFile::kDexNoIndex) { 192 *storage_index = storage_idx; 193 return std::make_pair(true, !resolved_member->IsFinal()); 194 } 195 } 196 } 197 // Conservative defaults. 198 *storage_index = DexFile::kDexNoIndex; 199 return std::make_pair(false, false); 200 } 201 202 inline std::pair<bool, bool> CompilerDriver::IsFastStaticField( 203 mirror::DexCache* dex_cache, mirror::Class* referrer_class, 204 ArtField* resolved_field, uint16_t field_idx, uint32_t* storage_index) { 205 return IsClassOfStaticMemberAvailableToReferrer( 206 dex_cache, referrer_class, resolved_field, field_idx, storage_index); 207 } 208 209 inline bool CompilerDriver::IsClassOfStaticMethodAvailableToReferrer( 210 mirror::DexCache* dex_cache, mirror::Class* referrer_class, 211 ArtMethod* resolved_method, uint16_t method_idx, uint32_t* storage_index) { 212 std::pair<bool, bool> result = IsClassOfStaticMemberAvailableToReferrer( 213 dex_cache, referrer_class, resolved_method, method_idx, storage_index); 214 // Only the first member of `result` is meaningful, as there is no 215 // "write access" to a method. 216 return result.first; 217 } 218 219 inline bool CompilerDriver::IsStaticFieldInReferrerClass(mirror::Class* referrer_class, 220 ArtField* resolved_field) { 221 DCHECK(resolved_field->IsStatic()); 222 mirror::Class* fields_class = resolved_field->GetDeclaringClass(); 223 return referrer_class == fields_class; 224 } 225 226 inline bool CompilerDriver::CanAssumeClassIsInitialized(mirror::Class* klass) { 227 // Being loaded is a pre-requisite for being initialized but let's do the cheap check first. 228 // 229 // NOTE: When AOT compiling an app, we eagerly initialize app classes (and potentially their 230 // super classes in the boot image) but only those that have a trivial initialization, i.e. 231 // without <clinit>() or static values in the dex file for that class or any of its super 232 // classes. So while we could see the klass as initialized during AOT compilation and have 233 // it only loaded at runtime, the needed initialization would have to be trivial and 234 // unobservable from Java, so we may as well treat it as initialized. 235 if (!klass->IsInitialized()) { 236 return false; 237 } 238 return CanAssumeClassIsLoaded(klass); 239 } 240 241 inline bool CompilerDriver::CanReferrerAssumeClassIsInitialized(mirror::Class* referrer_class, 242 mirror::Class* klass) { 243 return (referrer_class != nullptr 244 && !referrer_class->IsInterface() 245 && referrer_class->IsSubClass(klass)) 246 || CanAssumeClassIsInitialized(klass); 247 } 248 249 inline bool CompilerDriver::IsStaticFieldsClassInitialized(mirror::Class* referrer_class, 250 ArtField* resolved_field) { 251 DCHECK(resolved_field->IsStatic()); 252 mirror::Class* fields_class = resolved_field->GetDeclaringClass(); 253 return CanReferrerAssumeClassIsInitialized(referrer_class, fields_class); 254 } 255 256 inline ArtMethod* CompilerDriver::ResolveMethod( 257 ScopedObjectAccess& soa, Handle<mirror::DexCache> dex_cache, 258 Handle<mirror::ClassLoader> class_loader, const DexCompilationUnit* mUnit, 259 uint32_t method_idx, InvokeType invoke_type, bool check_incompatible_class_change) { 260 DCHECK_EQ(class_loader.Get(), soa.Decode<mirror::ClassLoader*>(mUnit->GetClassLoader())); 261 ArtMethod* resolved_method = 262 check_incompatible_class_change 263 ? mUnit->GetClassLinker()->ResolveMethod<ClassLinker::kForceICCECheck>( 264 *dex_cache->GetDexFile(), method_idx, dex_cache, class_loader, nullptr, invoke_type) 265 : mUnit->GetClassLinker()->ResolveMethod<ClassLinker::kNoICCECheckForCache>( 266 *dex_cache->GetDexFile(), method_idx, dex_cache, class_loader, nullptr, invoke_type); 267 if (UNLIKELY(resolved_method == nullptr)) { 268 DCHECK(soa.Self()->IsExceptionPending()); 269 // Clean up any exception left by type resolution. 270 soa.Self()->ClearException(); 271 } 272 return resolved_method; 273 } 274 275 inline void CompilerDriver::GetResolvedMethodDexFileLocation( 276 ArtMethod* resolved_method, const DexFile** declaring_dex_file, 277 uint16_t* declaring_class_idx, uint16_t* declaring_method_idx) { 278 mirror::Class* declaring_class = resolved_method->GetDeclaringClass(); 279 *declaring_dex_file = declaring_class->GetDexCache()->GetDexFile(); 280 *declaring_class_idx = declaring_class->GetDexTypeIndex(); 281 *declaring_method_idx = resolved_method->GetDexMethodIndex(); 282 } 283 284 inline uint16_t CompilerDriver::GetResolvedMethodVTableIndex( 285 ArtMethod* resolved_method, InvokeType type) { 286 if (type == kVirtual || type == kSuper) { 287 return resolved_method->GetMethodIndex(); 288 } else if (type == kInterface) { 289 return resolved_method->GetDexMethodIndex(); 290 } else { 291 return DexFile::kDexNoIndex16; 292 } 293 } 294 295 inline int CompilerDriver::IsFastInvoke( 296 ScopedObjectAccess& soa, Handle<mirror::DexCache> dex_cache, 297 Handle<mirror::ClassLoader> class_loader, const DexCompilationUnit* mUnit, 298 mirror::Class* referrer_class, ArtMethod* resolved_method, InvokeType* invoke_type, 299 MethodReference* target_method, const MethodReference* devirt_target, 300 uintptr_t* direct_code, uintptr_t* direct_method) { 301 // Don't try to fast-path if we don't understand the caller's class. 302 // Referrer_class is the class that this invoke is contained in. 303 if (UNLIKELY(referrer_class == nullptr)) { 304 return 0; 305 } 306 StackHandleScope<2> hs(soa.Self()); 307 // Methods_class is the class refered to by the class_idx field of the methodId the method_idx is 308 // pointing to. 309 // For example in 310 // .class LABC; 311 // .super LDEF; 312 // .method hi()V 313 // ... 314 // invoke-super {p0}, LDEF;->hi()V 315 // ... 316 // .end method 317 // the referrer_class is 'ABC' and the methods_class is DEF. Note that the methods class is 'DEF' 318 // even if 'DEF' inherits the method from it's superclass. 319 Handle<mirror::Class> methods_class(hs.NewHandle(mUnit->GetClassLinker()->ResolveType( 320 *target_method->dex_file, 321 target_method->dex_file->GetMethodId(target_method->dex_method_index).class_idx_, 322 dex_cache, 323 class_loader))); 324 DCHECK(methods_class.Get() != nullptr); 325 mirror::Class* methods_declaring_class = resolved_method->GetDeclaringClass(); 326 if (UNLIKELY(!referrer_class->CanAccessResolvedMethod(methods_declaring_class, resolved_method, 327 dex_cache.Get(), 328 target_method->dex_method_index))) { 329 return 0; 330 } 331 // Sharpen a virtual call into a direct call when the target is known not to have been 332 // overridden (ie is final). 333 const bool same_dex_file = target_method->dex_file == mUnit->GetDexFile(); 334 bool can_sharpen_virtual_based_on_type = same_dex_file && 335 (*invoke_type == kVirtual) && (resolved_method->IsFinal() || 336 methods_declaring_class->IsFinal()); 337 // For invoke-super, ensure the vtable index will be correct to dispatch in the vtable of 338 // the super class. 339 const size_t pointer_size = InstructionSetPointerSize(GetInstructionSet()); 340 // TODO We should be able to sharpen if we are going into the boot image as well. 341 bool can_sharpen_super_based_on_type = same_dex_file && 342 (*invoke_type == kSuper) && 343 !methods_class->IsInterface() && 344 (referrer_class != methods_declaring_class) && 345 referrer_class->IsSubClass(methods_declaring_class) && 346 resolved_method->GetMethodIndex() < methods_declaring_class->GetVTableLength() && 347 (methods_declaring_class->GetVTableEntry( 348 resolved_method->GetMethodIndex(), pointer_size) == resolved_method) && 349 resolved_method->IsInvokable(); 350 // TODO We should be able to sharpen if we are going into the boot image as well. 351 bool can_sharpen_interface_super_based_on_type = same_dex_file && 352 (*invoke_type == kSuper) && 353 methods_class->IsInterface() && 354 methods_class->IsAssignableFrom(referrer_class) && 355 resolved_method->IsInvokable(); 356 357 if (can_sharpen_virtual_based_on_type || 358 can_sharpen_super_based_on_type || 359 can_sharpen_interface_super_based_on_type) { 360 // Sharpen a virtual call into a direct call. The method_idx is into referrer's 361 // dex cache, check that this resolved method is where we expect it. 362 CHECK_EQ(target_method->dex_file, mUnit->GetDexFile()); 363 DCHECK_EQ(dex_cache.Get(), mUnit->GetClassLinker()->FindDexCache( 364 soa.Self(), *mUnit->GetDexFile(), false)); 365 CHECK_EQ(referrer_class->GetDexCache()->GetResolvedMethod( 366 target_method->dex_method_index, pointer_size), 367 resolved_method) << PrettyMethod(resolved_method); 368 int stats_flags = kFlagMethodResolved; 369 GetCodeAndMethodForDirectCall(/*out*/invoke_type, 370 kDirect, // Sharp type 371 false, // The dex cache is guaranteed to be available 372 referrer_class, resolved_method, 373 /*out*/&stats_flags, 374 target_method, 375 /*out*/direct_code, 376 /*out*/direct_method); 377 DCHECK_NE(*invoke_type, kSuper) << PrettyMethod(resolved_method); 378 if (*invoke_type == kDirect) { 379 stats_flags |= kFlagsMethodResolvedVirtualMadeDirect; 380 } 381 return stats_flags; 382 } 383 384 if ((*invoke_type == kVirtual || *invoke_type == kInterface) && devirt_target != nullptr) { 385 // Post-verification callback recorded a more precise invoke target based on its type info. 386 ArtMethod* called_method; 387 ClassLinker* class_linker = mUnit->GetClassLinker(); 388 if (LIKELY(devirt_target->dex_file == mUnit->GetDexFile())) { 389 called_method = class_linker->ResolveMethod<ClassLinker::kNoICCECheckForCache>( 390 *devirt_target->dex_file, devirt_target->dex_method_index, dex_cache, class_loader, 391 nullptr, kVirtual); 392 } else { 393 auto target_dex_cache(hs.NewHandle(class_linker->RegisterDexFile(*devirt_target->dex_file, 394 class_loader.Get()))); 395 called_method = class_linker->ResolveMethod<ClassLinker::kNoICCECheckForCache>( 396 *devirt_target->dex_file, devirt_target->dex_method_index, target_dex_cache, 397 class_loader, nullptr, kVirtual); 398 } 399 CHECK(called_method != nullptr); 400 CHECK(called_method->IsInvokable()); 401 int stats_flags = kFlagMethodResolved; 402 GetCodeAndMethodForDirectCall(/*out*/invoke_type, 403 kDirect, // Sharp type 404 true, // The dex cache may not be available 405 referrer_class, called_method, 406 /*out*/&stats_flags, 407 target_method, 408 /*out*/direct_code, 409 /*out*/direct_method); 410 DCHECK_NE(*invoke_type, kSuper); 411 if (*invoke_type == kDirect) { 412 stats_flags |= kFlagsMethodResolvedPreciseTypeDevirtualization; 413 } 414 return stats_flags; 415 } 416 417 if (UNLIKELY(*invoke_type == kSuper)) { 418 // Unsharpened super calls are suspicious so go slow-path. 419 return 0; 420 } 421 422 // Sharpening failed so generate a regular resolved method dispatch. 423 int stats_flags = kFlagMethodResolved; 424 GetCodeAndMethodForDirectCall(/*out*/invoke_type, 425 *invoke_type, // Sharp type 426 false, // The dex cache is guaranteed to be available 427 referrer_class, resolved_method, 428 /*out*/&stats_flags, 429 target_method, 430 /*out*/direct_code, 431 /*out*/direct_method); 432 return stats_flags; 433 } 434 435 inline bool CompilerDriver::IsMethodsClassInitialized(mirror::Class* referrer_class, 436 ArtMethod* resolved_method) { 437 if (!resolved_method->IsStatic()) { 438 return true; 439 } 440 mirror::Class* methods_class = resolved_method->GetDeclaringClass(); 441 return CanReferrerAssumeClassIsInitialized(referrer_class, methods_class); 442 } 443 444 } // namespace art 445 446 #endif // ART_COMPILER_DRIVER_COMPILER_DRIVER_INL_H_ 447