/* * Copyright (C) 2012 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef ART_COMPILER_DRIVER_COMPILER_DRIVER_INL_H_ #define ART_COMPILER_DRIVER_COMPILER_DRIVER_INL_H_ #include "compiler_driver.h" #include "art_field-inl.h" #include "art_method-inl.h" #include "base/enums.h" #include "class_linker-inl.h" #include "dex_compilation_unit.h" #include "mirror/class_loader.h" #include "mirror/dex_cache-inl.h" #include "scoped_thread_state_change-inl.h" #include "handle_scope-inl.h" namespace art { inline mirror::ClassLoader* CompilerDriver::GetClassLoader(const ScopedObjectAccess& soa, const DexCompilationUnit* mUnit) { return soa.Decode(mUnit->GetClassLoader()).Ptr(); } inline mirror::Class* CompilerDriver::ResolveClass( const ScopedObjectAccess& soa, Handle dex_cache, Handle class_loader, dex::TypeIndex cls_index, const DexCompilationUnit* mUnit) { DCHECK_EQ(dex_cache->GetDexFile(), mUnit->GetDexFile()); DCHECK_EQ(class_loader.Get(), GetClassLoader(soa, mUnit)); mirror::Class* cls = mUnit->GetClassLinker()->ResolveType( *mUnit->GetDexFile(), cls_index, dex_cache, class_loader); DCHECK_EQ(cls == nullptr, soa.Self()->IsExceptionPending()); if (UNLIKELY(cls == nullptr)) { // Clean up any exception left by type resolution. soa.Self()->ClearException(); } return cls; } inline mirror::Class* CompilerDriver::ResolveCompilingMethodsClass( const ScopedObjectAccess& soa, Handle dex_cache, Handle class_loader, const DexCompilationUnit* mUnit) { DCHECK_EQ(dex_cache->GetDexFile(), mUnit->GetDexFile()); DCHECK_EQ(class_loader.Get(), GetClassLoader(soa, mUnit)); const DexFile::MethodId& referrer_method_id = mUnit->GetDexFile()->GetMethodId(mUnit->GetDexMethodIndex()); return ResolveClass(soa, dex_cache, class_loader, referrer_method_id.class_idx_, mUnit); } inline ArtField* CompilerDriver::ResolveFieldWithDexFile( const ScopedObjectAccess& soa, Handle dex_cache, Handle class_loader, const DexFile* dex_file, uint32_t field_idx, bool is_static) { DCHECK_EQ(dex_cache->GetDexFile(), dex_file); ArtField* resolved_field = Runtime::Current()->GetClassLinker()->ResolveField( *dex_file, field_idx, dex_cache, class_loader, is_static); DCHECK_EQ(resolved_field == nullptr, soa.Self()->IsExceptionPending()); if (UNLIKELY(resolved_field == nullptr)) { // Clean up any exception left by type resolution. soa.Self()->ClearException(); return nullptr; } if (UNLIKELY(resolved_field->IsStatic() != is_static)) { // ClassLinker can return a field of the wrong kind directly from the DexCache. // Silently return null on such incompatible class change. return nullptr; } return resolved_field; } inline ArtField* CompilerDriver::ResolveField( const ScopedObjectAccess& soa, Handle dex_cache, Handle class_loader, const DexCompilationUnit* mUnit, uint32_t field_idx, bool is_static) { DCHECK_EQ(class_loader.Get(), GetClassLoader(soa, mUnit)); return ResolveFieldWithDexFile(soa, dex_cache, class_loader, mUnit->GetDexFile(), field_idx, is_static); } inline std::pair CompilerDriver::IsFastInstanceField( mirror::DexCache* dex_cache, mirror::Class* referrer_class, ArtField* resolved_field, uint16_t field_idx) { DCHECK(!resolved_field->IsStatic()); ObjPtr fields_class = resolved_field->GetDeclaringClass(); bool fast_get = referrer_class != nullptr && referrer_class->CanAccessResolvedField(fields_class, resolved_field, dex_cache, field_idx); bool fast_put = fast_get && (!resolved_field->IsFinal() || fields_class == referrer_class); return std::make_pair(fast_get, fast_put); } template inline bool CompilerDriver::CanAccessResolvedMember(mirror::Class* referrer_class ATTRIBUTE_UNUSED, mirror::Class* access_to ATTRIBUTE_UNUSED, ArtMember* member ATTRIBUTE_UNUSED, mirror::DexCache* dex_cache ATTRIBUTE_UNUSED, uint32_t field_idx ATTRIBUTE_UNUSED) { // Not defined for ArtMember values other than ArtField or ArtMethod. UNREACHABLE(); } template <> inline bool CompilerDriver::CanAccessResolvedMember(mirror::Class* referrer_class, mirror::Class* access_to, ArtField* field, mirror::DexCache* dex_cache, uint32_t field_idx) { return referrer_class->CanAccessResolvedField(access_to, field, dex_cache, field_idx); } template <> inline bool CompilerDriver::CanAccessResolvedMember( mirror::Class* referrer_class, mirror::Class* access_to, ArtMethod* method, mirror::DexCache* dex_cache, uint32_t field_idx) { return referrer_class->CanAccessResolvedMethod(access_to, method, dex_cache, field_idx); } inline ArtMethod* CompilerDriver::ResolveMethod( ScopedObjectAccess& soa, Handle dex_cache, Handle class_loader, const DexCompilationUnit* mUnit, uint32_t method_idx, InvokeType invoke_type, bool check_incompatible_class_change) { DCHECK_EQ(class_loader.Get(), GetClassLoader(soa, mUnit)); ArtMethod* resolved_method = check_incompatible_class_change ? mUnit->GetClassLinker()->ResolveMethod( *dex_cache->GetDexFile(), method_idx, dex_cache, class_loader, nullptr, invoke_type) : mUnit->GetClassLinker()->ResolveMethod( *dex_cache->GetDexFile(), method_idx, dex_cache, class_loader, nullptr, invoke_type); if (UNLIKELY(resolved_method == nullptr)) { DCHECK(soa.Self()->IsExceptionPending()); // Clean up any exception left by type resolution. soa.Self()->ClearException(); } return resolved_method; } } // namespace art #endif // ART_COMPILER_DRIVER_COMPILER_DRIVER_INL_H_