1 /* 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 #include "mir_field_info.h" 18 19 #include <string.h> 20 21 #include "base/logging.h" 22 #include "driver/compiler_driver.h" 23 #include "driver/compiler_driver-inl.h" 24 #include "mirror/class_loader.h" // Only to allow casts in Handle<ClassLoader>. 25 #include "mirror/dex_cache.h" // Only to allow casts in Handle<DexCache>. 26 #include "scoped_thread_state_change.h" 27 #include "handle_scope-inl.h" 28 29 namespace art { 30 31 void MirIFieldLoweringInfo::Resolve(CompilerDriver* compiler_driver, 32 const DexCompilationUnit* mUnit, 33 MirIFieldLoweringInfo* field_infos, size_t count) { 34 if (kIsDebugBuild) { 35 DCHECK(field_infos != nullptr); 36 DCHECK_NE(count, 0u); 37 for (auto it = field_infos, end = field_infos + count; it != end; ++it) { 38 MirIFieldLoweringInfo unresolved(it->field_idx_); 39 DCHECK_EQ(memcmp(&unresolved, &*it, sizeof(*it)), 0); 40 } 41 } 42 43 // We're going to resolve fields and check access in a tight loop. It's better to hold 44 // the lock and needed references once than re-acquiring them again and again. 45 ScopedObjectAccess soa(Thread::Current()); 46 StackHandleScope<3> hs(soa.Self()); 47 Handle<mirror::DexCache> dex_cache(hs.NewHandle(compiler_driver->GetDexCache(mUnit))); 48 Handle<mirror::ClassLoader> class_loader( 49 hs.NewHandle(compiler_driver->GetClassLoader(soa, mUnit))); 50 Handle<mirror::Class> referrer_class(hs.NewHandle( 51 compiler_driver->ResolveCompilingMethodsClass(soa, dex_cache, class_loader, mUnit))); 52 // Even if the referrer class is unresolved (i.e. we're compiling a method without class 53 // definition) we still want to resolve fields and record all available info. 54 55 for (auto it = field_infos, end = field_infos + count; it != end; ++it) { 56 uint32_t field_idx = it->field_idx_; 57 mirror::ArtField* resolved_field = 58 compiler_driver->ResolveField(soa, dex_cache, class_loader, mUnit, field_idx, false); 59 if (UNLIKELY(resolved_field == nullptr)) { 60 continue; 61 } 62 compiler_driver->GetResolvedFieldDexFileLocation(resolved_field, 63 &it->declaring_dex_file_, &it->declaring_class_idx_, &it->declaring_field_idx_); 64 bool is_volatile = compiler_driver->IsFieldVolatile(resolved_field); 65 it->field_offset_ = resolved_field->GetOffset(); 66 std::pair<bool, bool> fast_path = compiler_driver->IsFastInstanceField( 67 dex_cache.Get(), referrer_class.Get(), resolved_field, field_idx); 68 it->flags_ = 0u | // Without kFlagIsStatic. 69 (is_volatile ? kFlagIsVolatile : 0u) | 70 (fast_path.first ? kFlagFastGet : 0u) | 71 (fast_path.second ? kFlagFastPut : 0u); 72 } 73 } 74 75 void MirSFieldLoweringInfo::Resolve(CompilerDriver* compiler_driver, 76 const DexCompilationUnit* mUnit, 77 MirSFieldLoweringInfo* field_infos, size_t count) { 78 if (kIsDebugBuild) { 79 DCHECK(field_infos != nullptr); 80 DCHECK_NE(count, 0u); 81 for (auto it = field_infos, end = field_infos + count; it != end; ++it) { 82 MirSFieldLoweringInfo unresolved(it->field_idx_); 83 // In 64-bit builds, there's padding after storage_index_, don't include it in memcmp. 84 size_t size = OFFSETOF_MEMBER(MirSFieldLoweringInfo, storage_index_) + 85 sizeof(it->storage_index_); 86 DCHECK_EQ(memcmp(&unresolved, &*it, size), 0); 87 } 88 } 89 90 // We're going to resolve fields and check access in a tight loop. It's better to hold 91 // the lock and needed references once than re-acquiring them again and again. 92 ScopedObjectAccess soa(Thread::Current()); 93 StackHandleScope<3> hs(soa.Self()); 94 Handle<mirror::DexCache> dex_cache(hs.NewHandle(compiler_driver->GetDexCache(mUnit))); 95 Handle<mirror::ClassLoader> class_loader( 96 hs.NewHandle(compiler_driver->GetClassLoader(soa, mUnit))); 97 Handle<mirror::Class> referrer_class(hs.NewHandle( 98 compiler_driver->ResolveCompilingMethodsClass(soa, dex_cache, class_loader, mUnit))); 99 // Even if the referrer class is unresolved (i.e. we're compiling a method without class 100 // definition) we still want to resolve fields and record all available info. 101 102 for (auto it = field_infos, end = field_infos + count; it != end; ++it) { 103 uint32_t field_idx = it->field_idx_; 104 mirror::ArtField* resolved_field = 105 compiler_driver->ResolveField(soa, dex_cache, class_loader, mUnit, field_idx, true); 106 if (UNLIKELY(resolved_field == nullptr)) { 107 continue; 108 } 109 compiler_driver->GetResolvedFieldDexFileLocation(resolved_field, 110 &it->declaring_dex_file_, &it->declaring_class_idx_, &it->declaring_field_idx_); 111 bool is_volatile = compiler_driver->IsFieldVolatile(resolved_field) ? 1u : 0u; 112 113 bool is_referrers_class, is_initialized; 114 std::pair<bool, bool> fast_path = compiler_driver->IsFastStaticField( 115 dex_cache.Get(), referrer_class.Get(), resolved_field, field_idx, &it->field_offset_, 116 &it->storage_index_, &is_referrers_class, &is_initialized); 117 it->flags_ = kFlagIsStatic | 118 (is_volatile ? kFlagIsVolatile : 0u) | 119 (fast_path.first ? kFlagFastGet : 0u) | 120 (fast_path.second ? kFlagFastPut : 0u) | 121 (is_referrers_class ? kFlagIsReferrersClass : 0u) | 122 (is_initialized ? kFlagIsInitialized : 0u); 123 } 124 } 125 126 } // namespace art 127