| Vladimir Marko | be0e546 | 2014-02-26 11:24:15 +0000 | [diff] [blame] | 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" | 
| Mingyao Yang | 98d1cc8 | 2014-05-15 17:02:16 -0700 | [diff] [blame] | 21 |  | 
| Vladimir Marko | be0e546 | 2014-02-26 11:24:15 +0000 | [diff] [blame] | 22 | #include "dex/compiler_ir.h" | 
| Andreas Gampe | 53c913b | 2014-08-12 23:19:23 -0700 | [diff] [blame^] | 23 | #include "dex_compilation_unit.h" | 
| Ian Rogers | 22d5e73 | 2014-07-15 22:23:51 -0700 | [diff] [blame] | 24 | #include "field_helper.h" | 
| Vladimir Marko | be0e546 | 2014-02-26 11:24:15 +0000 | [diff] [blame] | 25 | #include "mirror/art_field-inl.h" | 
| Vladimir Marko | f096aad | 2014-01-23 15:51:58 +0000 | [diff] [blame] | 26 | #include "mirror/art_method-inl.h" | 
| Vladimir Marko | be0e546 | 2014-02-26 11:24:15 +0000 | [diff] [blame] | 27 | #include "mirror/class_loader.h" | 
| Vladimir Marko | f096aad | 2014-01-23 15:51:58 +0000 | [diff] [blame] | 28 | #include "mirror/dex_cache-inl.h" | 
| Vladimir Marko | be0e546 | 2014-02-26 11:24:15 +0000 | [diff] [blame] | 29 | #include "mirror/art_field-inl.h" | 
 | 30 | #include "scoped_thread_state_change.h" | 
| Mathieu Chartier | eb8167a | 2014-05-07 15:43:14 -0700 | [diff] [blame] | 31 | #include "handle_scope-inl.h" | 
| Vladimir Marko | be0e546 | 2014-02-26 11:24:15 +0000 | [diff] [blame] | 32 |  | 
 | 33 | namespace art { | 
 | 34 |  | 
 | 35 | inline mirror::DexCache* CompilerDriver::GetDexCache(const DexCompilationUnit* mUnit) { | 
 | 36 |   return mUnit->GetClassLinker()->FindDexCache(*mUnit->GetDexFile()); | 
 | 37 | } | 
 | 38 |  | 
 | 39 | inline mirror::ClassLoader* CompilerDriver::GetClassLoader(ScopedObjectAccess& soa, | 
 | 40 |                                                            const DexCompilationUnit* mUnit) { | 
 | 41 |   return soa.Decode<mirror::ClassLoader*>(mUnit->GetClassLoader()); | 
 | 42 | } | 
 | 43 |  | 
 | 44 | inline mirror::Class* CompilerDriver::ResolveCompilingMethodsClass( | 
| Nicolas Geoffray | e503832 | 2014-07-04 09:41:32 +0100 | [diff] [blame] | 45 |     const ScopedObjectAccess& soa, Handle<mirror::DexCache> dex_cache, | 
| Mathieu Chartier | 0cd8135 | 2014-05-22 16:48:55 -0700 | [diff] [blame] | 46 |     Handle<mirror::ClassLoader> class_loader, const DexCompilationUnit* mUnit) { | 
| Mathieu Chartier | eb8167a | 2014-05-07 15:43:14 -0700 | [diff] [blame] | 47 |   DCHECK_EQ(dex_cache->GetDexFile(), mUnit->GetDexFile()); | 
 | 48 |   DCHECK_EQ(class_loader.Get(), soa.Decode<mirror::ClassLoader*>(mUnit->GetClassLoader())); | 
| Vladimir Marko | be0e546 | 2014-02-26 11:24:15 +0000 | [diff] [blame] | 49 |   const DexFile::MethodId& referrer_method_id = | 
 | 50 |       mUnit->GetDexFile()->GetMethodId(mUnit->GetDexMethodIndex()); | 
 | 51 |   mirror::Class* referrer_class = mUnit->GetClassLinker()->ResolveType( | 
 | 52 |       *mUnit->GetDexFile(), referrer_method_id.class_idx_, dex_cache, class_loader); | 
 | 53 |   DCHECK_EQ(referrer_class == nullptr, soa.Self()->IsExceptionPending()); | 
 | 54 |   if (UNLIKELY(referrer_class == nullptr)) { | 
 | 55 |     // Clean up any exception left by type resolution. | 
 | 56 |     soa.Self()->ClearException(); | 
 | 57 |   } | 
 | 58 |   return referrer_class; | 
 | 59 | } | 
 | 60 |  | 
 | 61 | inline mirror::ArtField* CompilerDriver::ResolveField( | 
| Nicolas Geoffray | e503832 | 2014-07-04 09:41:32 +0100 | [diff] [blame] | 62 |     const ScopedObjectAccess& soa, Handle<mirror::DexCache> dex_cache, | 
| Mathieu Chartier | 0cd8135 | 2014-05-22 16:48:55 -0700 | [diff] [blame] | 63 |     Handle<mirror::ClassLoader> class_loader, const DexCompilationUnit* mUnit, | 
| Vladimir Marko | be0e546 | 2014-02-26 11:24:15 +0000 | [diff] [blame] | 64 |     uint32_t field_idx, bool is_static) { | 
| Mathieu Chartier | eb8167a | 2014-05-07 15:43:14 -0700 | [diff] [blame] | 65 |   DCHECK_EQ(dex_cache->GetDexFile(), mUnit->GetDexFile()); | 
 | 66 |   DCHECK_EQ(class_loader.Get(), soa.Decode<mirror::ClassLoader*>(mUnit->GetClassLoader())); | 
| Vladimir Marko | be0e546 | 2014-02-26 11:24:15 +0000 | [diff] [blame] | 67 |   mirror::ArtField* resolved_field = mUnit->GetClassLinker()->ResolveField( | 
 | 68 |       *mUnit->GetDexFile(), field_idx, dex_cache, class_loader, is_static); | 
 | 69 |   DCHECK_EQ(resolved_field == nullptr, soa.Self()->IsExceptionPending()); | 
 | 70 |   if (UNLIKELY(resolved_field == nullptr)) { | 
 | 71 |     // Clean up any exception left by type resolution. | 
 | 72 |     soa.Self()->ClearException(); | 
 | 73 |     return nullptr; | 
 | 74 |   } | 
 | 75 |   if (UNLIKELY(resolved_field->IsStatic() != is_static)) { | 
 | 76 |     // ClassLinker can return a field of the wrong kind directly from the DexCache. | 
 | 77 |     // Silently return nullptr on such incompatible class change. | 
 | 78 |     return nullptr; | 
 | 79 |   } | 
 | 80 |   return resolved_field; | 
 | 81 | } | 
 | 82 |  | 
 | 83 | inline void CompilerDriver::GetResolvedFieldDexFileLocation( | 
 | 84 |     mirror::ArtField* resolved_field, const DexFile** declaring_dex_file, | 
 | 85 |     uint16_t* declaring_class_idx, uint16_t* declaring_field_idx) { | 
 | 86 |   mirror::Class* declaring_class = resolved_field->GetDeclaringClass(); | 
 | 87 |   *declaring_dex_file = declaring_class->GetDexCache()->GetDexFile(); | 
 | 88 |   *declaring_class_idx = declaring_class->GetDexTypeIndex(); | 
 | 89 |   *declaring_field_idx = resolved_field->GetDexFieldIndex(); | 
 | 90 | } | 
 | 91 |  | 
 | 92 | inline bool CompilerDriver::IsFieldVolatile(mirror::ArtField* field) { | 
 | 93 |   return field->IsVolatile(); | 
 | 94 | } | 
 | 95 |  | 
 | 96 | inline std::pair<bool, bool> CompilerDriver::IsFastInstanceField( | 
 | 97 |     mirror::DexCache* dex_cache, mirror::Class* referrer_class, | 
| Nicolas Geoffray | e503832 | 2014-07-04 09:41:32 +0100 | [diff] [blame] | 98 |     mirror::ArtField* resolved_field, uint16_t field_idx) { | 
| Vladimir Marko | be0e546 | 2014-02-26 11:24:15 +0000 | [diff] [blame] | 99 |   DCHECK(!resolved_field->IsStatic()); | 
 | 100 |   mirror::Class* fields_class = resolved_field->GetDeclaringClass(); | 
 | 101 |   bool fast_get = referrer_class != nullptr && | 
 | 102 |       referrer_class->CanAccessResolvedField(fields_class, resolved_field, | 
 | 103 |                                              dex_cache, field_idx); | 
 | 104 |   bool fast_put = fast_get && (!resolved_field->IsFinal() || fields_class == referrer_class); | 
| Vladimir Marko | be0e546 | 2014-02-26 11:24:15 +0000 | [diff] [blame] | 105 |   return std::make_pair(fast_get, fast_put); | 
 | 106 | } | 
 | 107 |  | 
 | 108 | inline std::pair<bool, bool> CompilerDriver::IsFastStaticField( | 
 | 109 |     mirror::DexCache* dex_cache, mirror::Class* referrer_class, | 
 | 110 |     mirror::ArtField* resolved_field, uint16_t field_idx, MemberOffset* field_offset, | 
 | 111 |     uint32_t* storage_index, bool* is_referrers_class, bool* is_initialized) { | 
 | 112 |   DCHECK(resolved_field->IsStatic()); | 
 | 113 |   if (LIKELY(referrer_class != nullptr)) { | 
 | 114 |     mirror::Class* fields_class = resolved_field->GetDeclaringClass(); | 
 | 115 |     if (fields_class == referrer_class) { | 
 | 116 |       *field_offset = resolved_field->GetOffset(); | 
 | 117 |       *storage_index = fields_class->GetDexTypeIndex(); | 
 | 118 |       *is_referrers_class = true;  // implies no worrying about class initialization | 
 | 119 |       *is_initialized = true; | 
 | 120 |       return std::make_pair(true, true); | 
 | 121 |     } | 
 | 122 |     if (referrer_class->CanAccessResolvedField(fields_class, resolved_field, | 
 | 123 |                                                dex_cache, field_idx)) { | 
 | 124 |       // We have the resolved field, we must make it into a index for the referrer | 
 | 125 |       // in its static storage (which may fail if it doesn't have a slot for it) | 
 | 126 |       // TODO: for images we can elide the static storage base null check | 
 | 127 |       // if we know there's a non-null entry in the image | 
 | 128 |       const DexFile* dex_file = dex_cache->GetDexFile(); | 
 | 129 |       uint32_t storage_idx = DexFile::kDexNoIndex; | 
 | 130 |       if (LIKELY(fields_class->GetDexCache() == dex_cache)) { | 
 | 131 |         // common case where the dex cache of both the referrer and the field are the same, | 
 | 132 |         // no need to search the dex file | 
 | 133 |         storage_idx = fields_class->GetDexTypeIndex(); | 
 | 134 |       } else { | 
 | 135 |         // Search dex file for localized ssb index, may fail if field's class is a parent | 
 | 136 |         // of the class mentioned in the dex file and there is no dex cache entry. | 
| Mathieu Chartier | 61c5ebc | 2014-06-05 17:42:53 -0700 | [diff] [blame] | 137 |         StackHandleScope<1> hs(Thread::Current()); | 
| Vladimir Marko | be0e546 | 2014-02-26 11:24:15 +0000 | [diff] [blame] | 138 |         const DexFile::StringId* string_id = | 
| Mathieu Chartier | 61c5ebc | 2014-06-05 17:42:53 -0700 | [diff] [blame] | 139 |             dex_file->FindStringId( | 
 | 140 |                 FieldHelper(hs.NewHandle(resolved_field)).GetDeclaringClassDescriptor()); | 
| Vladimir Marko | be0e546 | 2014-02-26 11:24:15 +0000 | [diff] [blame] | 141 |         if (string_id != nullptr) { | 
 | 142 |           const DexFile::TypeId* type_id = | 
 | 143 |              dex_file->FindTypeId(dex_file->GetIndexForStringId(*string_id)); | 
 | 144 |           if (type_id != nullptr) { | 
 | 145 |             // medium path, needs check of static storage base being initialized | 
 | 146 |             storage_idx = dex_file->GetIndexForTypeId(*type_id); | 
 | 147 |           } | 
 | 148 |         } | 
 | 149 |       } | 
 | 150 |       if (storage_idx != DexFile::kDexNoIndex) { | 
 | 151 |         *field_offset = resolved_field->GetOffset(); | 
 | 152 |         *storage_index = storage_idx; | 
 | 153 |         *is_referrers_class = false; | 
 | 154 |         *is_initialized = fields_class->IsInitialized() && | 
 | 155 |             CanAssumeTypeIsPresentInDexCache(*dex_file, storage_idx); | 
 | 156 |         return std::make_pair(true, !resolved_field->IsFinal()); | 
 | 157 |       } | 
 | 158 |     } | 
 | 159 |   } | 
 | 160 |   // Conservative defaults. | 
 | 161 |   *field_offset = MemberOffset(0u); | 
 | 162 |   *storage_index = DexFile::kDexNoIndex; | 
 | 163 |   *is_referrers_class = false; | 
 | 164 |   *is_initialized = false; | 
 | 165 |   return std::make_pair(false, false); | 
 | 166 | } | 
 | 167 |  | 
| Vladimir Marko | f096aad | 2014-01-23 15:51:58 +0000 | [diff] [blame] | 168 | inline mirror::ArtMethod* CompilerDriver::ResolveMethod( | 
| Mathieu Chartier | 0cd8135 | 2014-05-22 16:48:55 -0700 | [diff] [blame] | 169 |     ScopedObjectAccess& soa, Handle<mirror::DexCache> dex_cache, | 
 | 170 |     Handle<mirror::ClassLoader> class_loader, const DexCompilationUnit* mUnit, | 
| Vladimir Marko | f096aad | 2014-01-23 15:51:58 +0000 | [diff] [blame] | 171 |     uint32_t method_idx, InvokeType invoke_type) { | 
| Mathieu Chartier | 0cd8135 | 2014-05-22 16:48:55 -0700 | [diff] [blame] | 172 |   DCHECK_EQ(dex_cache->GetDexFile(), mUnit->GetDexFile()); | 
 | 173 |   DCHECK_EQ(class_loader.Get(), soa.Decode<mirror::ClassLoader*>(mUnit->GetClassLoader())); | 
| Vladimir Marko | f096aad | 2014-01-23 15:51:58 +0000 | [diff] [blame] | 174 |   mirror::ArtMethod* resolved_method = mUnit->GetClassLinker()->ResolveMethod( | 
| Mathieu Chartier | 0cd8135 | 2014-05-22 16:48:55 -0700 | [diff] [blame] | 175 |       *mUnit->GetDexFile(), method_idx, dex_cache, class_loader, NullHandle<mirror::ArtMethod>(), | 
 | 176 |       invoke_type); | 
| Vladimir Marko | f096aad | 2014-01-23 15:51:58 +0000 | [diff] [blame] | 177 |   DCHECK_EQ(resolved_method == nullptr, soa.Self()->IsExceptionPending()); | 
 | 178 |   if (UNLIKELY(resolved_method == nullptr)) { | 
 | 179 |     // Clean up any exception left by type resolution. | 
 | 180 |     soa.Self()->ClearException(); | 
 | 181 |     return nullptr; | 
 | 182 |   } | 
 | 183 |   if (UNLIKELY(resolved_method->CheckIncompatibleClassChange(invoke_type))) { | 
 | 184 |     // Silently return nullptr on incompatible class change. | 
 | 185 |     return nullptr; | 
 | 186 |   } | 
 | 187 |   return resolved_method; | 
 | 188 | } | 
 | 189 |  | 
 | 190 | inline void CompilerDriver::GetResolvedMethodDexFileLocation( | 
 | 191 |     mirror::ArtMethod* resolved_method, const DexFile** declaring_dex_file, | 
 | 192 |     uint16_t* declaring_class_idx, uint16_t* declaring_method_idx) { | 
 | 193 |   mirror::Class* declaring_class = resolved_method->GetDeclaringClass(); | 
 | 194 |   *declaring_dex_file = declaring_class->GetDexCache()->GetDexFile(); | 
 | 195 |   *declaring_class_idx = declaring_class->GetDexTypeIndex(); | 
 | 196 |   *declaring_method_idx = resolved_method->GetDexMethodIndex(); | 
 | 197 | } | 
 | 198 |  | 
 | 199 | inline uint16_t CompilerDriver::GetResolvedMethodVTableIndex( | 
 | 200 |     mirror::ArtMethod* resolved_method, InvokeType type) { | 
 | 201 |   if (type == kVirtual || type == kSuper) { | 
 | 202 |     return resolved_method->GetMethodIndex(); | 
 | 203 |   } else if (type == kInterface) { | 
 | 204 |     return resolved_method->GetDexMethodIndex(); | 
 | 205 |   } else { | 
 | 206 |     return DexFile::kDexNoIndex16; | 
 | 207 |   } | 
 | 208 | } | 
 | 209 |  | 
 | 210 | inline int CompilerDriver::IsFastInvoke( | 
| Mathieu Chartier | 0cd8135 | 2014-05-22 16:48:55 -0700 | [diff] [blame] | 211 |     ScopedObjectAccess& soa, Handle<mirror::DexCache> dex_cache, | 
 | 212 |     Handle<mirror::ClassLoader> class_loader, const DexCompilationUnit* mUnit, | 
| Vladimir Marko | f096aad | 2014-01-23 15:51:58 +0000 | [diff] [blame] | 213 |     mirror::Class* referrer_class, mirror::ArtMethod* resolved_method, InvokeType* invoke_type, | 
 | 214 |     MethodReference* target_method, const MethodReference* devirt_target, | 
 | 215 |     uintptr_t* direct_code, uintptr_t* direct_method) { | 
 | 216 |   // Don't try to fast-path if we don't understand the caller's class. | 
 | 217 |   if (UNLIKELY(referrer_class == nullptr)) { | 
 | 218 |     return 0; | 
 | 219 |   } | 
 | 220 |   mirror::Class* methods_class = resolved_method->GetDeclaringClass(); | 
 | 221 |   if (UNLIKELY(!referrer_class->CanAccessResolvedMethod(methods_class, resolved_method, | 
| Mathieu Chartier | eb8167a | 2014-05-07 15:43:14 -0700 | [diff] [blame] | 222 |                                                         dex_cache.Get(), | 
| Vladimir Marko | f096aad | 2014-01-23 15:51:58 +0000 | [diff] [blame] | 223 |                                                         target_method->dex_method_index))) { | 
 | 224 |     return 0; | 
 | 225 |   } | 
 | 226 |  | 
 | 227 |   // Sharpen a virtual call into a direct call when the target is known not to have been | 
 | 228 |   // overridden (ie is final). | 
 | 229 |   bool can_sharpen_virtual_based_on_type = | 
 | 230 |       (*invoke_type == kVirtual) && (resolved_method->IsFinal() || methods_class->IsFinal()); | 
 | 231 |   // For invoke-super, ensure the vtable index will be correct to dispatch in the vtable of | 
 | 232 |   // the super class. | 
 | 233 |   bool can_sharpen_super_based_on_type = (*invoke_type == kSuper) && | 
 | 234 |       (referrer_class != methods_class) && referrer_class->IsSubClass(methods_class) && | 
| Mingyao Yang | 2cdbad7 | 2014-07-16 10:44:41 -0700 | [diff] [blame] | 235 |       resolved_method->GetMethodIndex() < methods_class->GetVTableLength() && | 
 | 236 |       (methods_class->GetVTableEntry(resolved_method->GetMethodIndex()) == resolved_method); | 
| Vladimir Marko | f096aad | 2014-01-23 15:51:58 +0000 | [diff] [blame] | 237 |  | 
 | 238 |   if (can_sharpen_virtual_based_on_type || can_sharpen_super_based_on_type) { | 
 | 239 |     // Sharpen a virtual call into a direct call. The method_idx is into referrer's | 
 | 240 |     // dex cache, check that this resolved method is where we expect it. | 
 | 241 |     CHECK(target_method->dex_file == mUnit->GetDexFile()); | 
| Mathieu Chartier | eb8167a | 2014-05-07 15:43:14 -0700 | [diff] [blame] | 242 |     DCHECK(dex_cache.Get() == mUnit->GetClassLinker()->FindDexCache(*mUnit->GetDexFile())); | 
| Vladimir Marko | f096aad | 2014-01-23 15:51:58 +0000 | [diff] [blame] | 243 |     CHECK(referrer_class->GetDexCache()->GetResolvedMethod(target_method->dex_method_index) == | 
 | 244 |         resolved_method) << PrettyMethod(resolved_method); | 
 | 245 |     int stats_flags = kFlagMethodResolved; | 
 | 246 |     GetCodeAndMethodForDirectCall(invoke_type, kDirect, false, referrer_class, resolved_method, | 
 | 247 |                                   &stats_flags, target_method, direct_code, direct_method); | 
 | 248 |     DCHECK_NE(*invoke_type, kSuper) << PrettyMethod(resolved_method); | 
 | 249 |     if (*invoke_type == kDirect) { | 
 | 250 |       stats_flags |= kFlagsMethodResolvedVirtualMadeDirect; | 
 | 251 |     } | 
 | 252 |     return stats_flags; | 
 | 253 |   } | 
 | 254 |  | 
 | 255 |   if ((*invoke_type == kVirtual || *invoke_type == kInterface) && devirt_target != nullptr) { | 
 | 256 |     // Post-verification callback recorded a more precise invoke target based on its type info. | 
 | 257 |     mirror::ArtMethod* called_method; | 
 | 258 |     ClassLinker* class_linker = mUnit->GetClassLinker(); | 
 | 259 |     if (LIKELY(devirt_target->dex_file == mUnit->GetDexFile())) { | 
 | 260 |       called_method = class_linker->ResolveMethod(*devirt_target->dex_file, | 
| Mathieu Chartier | 0cd8135 | 2014-05-22 16:48:55 -0700 | [diff] [blame] | 261 |                                                   devirt_target->dex_method_index, dex_cache, | 
 | 262 |                                                   class_loader, NullHandle<mirror::ArtMethod>(), | 
 | 263 |                                                   kVirtual); | 
| Vladimir Marko | f096aad | 2014-01-23 15:51:58 +0000 | [diff] [blame] | 264 |     } else { | 
| Mathieu Chartier | eb8167a | 2014-05-07 15:43:14 -0700 | [diff] [blame] | 265 |       StackHandleScope<1> hs(soa.Self()); | 
 | 266 |       Handle<mirror::DexCache> target_dex_cache( | 
 | 267 |           hs.NewHandle(class_linker->FindDexCache(*devirt_target->dex_file))); | 
| Vladimir Marko | f096aad | 2014-01-23 15:51:58 +0000 | [diff] [blame] | 268 |       called_method = class_linker->ResolveMethod(*devirt_target->dex_file, | 
 | 269 |                                                   devirt_target->dex_method_index, | 
| Mathieu Chartier | 0cd8135 | 2014-05-22 16:48:55 -0700 | [diff] [blame] | 270 |                                                   target_dex_cache, class_loader, | 
 | 271 |                                                   NullHandle<mirror::ArtMethod>(), kVirtual); | 
| Vladimir Marko | f096aad | 2014-01-23 15:51:58 +0000 | [diff] [blame] | 272 |     } | 
 | 273 |     CHECK(called_method != NULL); | 
 | 274 |     CHECK(!called_method->IsAbstract()); | 
 | 275 |     int stats_flags = kFlagMethodResolved; | 
 | 276 |     GetCodeAndMethodForDirectCall(invoke_type, kDirect, true, referrer_class, called_method, | 
 | 277 |                                   &stats_flags, target_method, direct_code, direct_method); | 
 | 278 |     DCHECK_NE(*invoke_type, kSuper); | 
 | 279 |     if (*invoke_type == kDirect) { | 
 | 280 |       stats_flags |= kFlagsMethodResolvedPreciseTypeDevirtualization; | 
 | 281 |     } | 
 | 282 |     return stats_flags; | 
 | 283 |   } | 
 | 284 |  | 
 | 285 |   if (UNLIKELY(*invoke_type == kSuper)) { | 
 | 286 |     // Unsharpened super calls are suspicious so go slow-path. | 
 | 287 |     return 0; | 
 | 288 |   } | 
 | 289 |  | 
 | 290 |   // Sharpening failed so generate a regular resolved method dispatch. | 
 | 291 |   int stats_flags = kFlagMethodResolved; | 
 | 292 |   GetCodeAndMethodForDirectCall(invoke_type, *invoke_type, false, referrer_class, resolved_method, | 
 | 293 |                                 &stats_flags, target_method, direct_code, direct_method); | 
 | 294 |   return stats_flags; | 
 | 295 | } | 
 | 296 |  | 
| Vladimir Marko | 9820b7c | 2014-01-02 16:40:37 +0000 | [diff] [blame] | 297 | inline bool CompilerDriver::NeedsClassInitialization(mirror::Class* referrer_class, | 
 | 298 |                                                      mirror::ArtMethod* resolved_method) { | 
 | 299 |   if (!resolved_method->IsStatic()) { | 
 | 300 |     return false; | 
 | 301 |   } | 
 | 302 |   mirror::Class* methods_class = resolved_method->GetDeclaringClass(); | 
 | 303 |   // NOTE: Unlike in IsFastStaticField(), we don't check CanAssumeTypeIsPresentInDexCache() here. | 
 | 304 |   return methods_class != referrer_class && !methods_class->IsInitialized(); | 
 | 305 | } | 
 | 306 |  | 
| Vladimir Marko | be0e546 | 2014-02-26 11:24:15 +0000 | [diff] [blame] | 307 | }  // namespace art | 
 | 308 |  | 
 | 309 | #endif  // ART_COMPILER_DRIVER_COMPILER_DRIVER_INL_H_ |