Home | History | Annotate | Download | only in mirror
      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 #include "dex_cache-inl.h"
     18 
     19 #include "art_method-inl.h"
     20 #include "base/logging.h"
     21 #include "class_linker.h"
     22 #include "gc/accounting/card_table-inl.h"
     23 #include "gc/heap.h"
     24 #include "globals.h"
     25 #include "linear_alloc.h"
     26 #include "oat_file.h"
     27 #include "object.h"
     28 #include "object-inl.h"
     29 #include "object_array-inl.h"
     30 #include "runtime.h"
     31 #include "string.h"
     32 #include "thread.h"
     33 #include "utils/dex_cache_arrays_layout-inl.h"
     34 
     35 namespace art {
     36 namespace mirror {
     37 
     38 void DexCache::InitializeDexCache(Thread* self,
     39                                   ObjPtr<mirror::DexCache> dex_cache,
     40                                   ObjPtr<mirror::String> location,
     41                                   const DexFile* dex_file,
     42                                   LinearAlloc* linear_alloc,
     43                                   PointerSize image_pointer_size) {
     44   DCHECK(dex_file != nullptr);
     45   ScopedAssertNoThreadSuspension sants(__FUNCTION__);
     46   DexCacheArraysLayout layout(image_pointer_size, dex_file);
     47   uint8_t* raw_arrays = nullptr;
     48 
     49   const OatDexFile* const oat_dex = dex_file->GetOatDexFile();
     50   if (oat_dex != nullptr && oat_dex->GetDexCacheArrays() != nullptr) {
     51     raw_arrays = oat_dex->GetDexCacheArrays();
     52   } else if (dex_file->NumStringIds() != 0u ||
     53              dex_file->NumTypeIds() != 0u ||
     54              dex_file->NumMethodIds() != 0u ||
     55              dex_file->NumFieldIds() != 0u) {
     56     static_assert(ArenaAllocator::kAlignment == 8, "Expecting arena alignment of 8.");
     57     DCHECK(layout.Alignment() == 8u || layout.Alignment() == 16u);
     58     // Zero-initialized.
     59     raw_arrays = (layout.Alignment() == 16u)
     60         ? reinterpret_cast<uint8_t*>(linear_alloc->AllocAlign16(self, layout.Size()))
     61         : reinterpret_cast<uint8_t*>(linear_alloc->Alloc(self, layout.Size()));
     62   }
     63 
     64   StringDexCacheType* strings = (dex_file->NumStringIds() == 0u) ? nullptr :
     65       reinterpret_cast<StringDexCacheType*>(raw_arrays + layout.StringsOffset());
     66   TypeDexCacheType* types = (dex_file->NumTypeIds() == 0u) ? nullptr :
     67       reinterpret_cast<TypeDexCacheType*>(raw_arrays + layout.TypesOffset());
     68   MethodDexCacheType* methods = (dex_file->NumMethodIds() == 0u) ? nullptr :
     69       reinterpret_cast<MethodDexCacheType*>(raw_arrays + layout.MethodsOffset());
     70   FieldDexCacheType* fields = (dex_file->NumFieldIds() == 0u) ? nullptr :
     71       reinterpret_cast<FieldDexCacheType*>(raw_arrays + layout.FieldsOffset());
     72 
     73   size_t num_strings = kDexCacheStringCacheSize;
     74   if (dex_file->NumStringIds() < num_strings) {
     75     num_strings = dex_file->NumStringIds();
     76   }
     77   size_t num_types = kDexCacheTypeCacheSize;
     78   if (dex_file->NumTypeIds() < num_types) {
     79     num_types = dex_file->NumTypeIds();
     80   }
     81   size_t num_fields = kDexCacheFieldCacheSize;
     82   if (dex_file->NumFieldIds() < num_fields) {
     83     num_fields = dex_file->NumFieldIds();
     84   }
     85   size_t num_methods = kDexCacheMethodCacheSize;
     86   if (dex_file->NumMethodIds() < num_methods) {
     87     num_methods = dex_file->NumMethodIds();
     88   }
     89 
     90   // Note that we allocate the method type dex caches regardless of this flag,
     91   // and we make sure here that they're not used by the runtime. This is in the
     92   // interest of simplicity and to avoid extensive compiler and layout class changes.
     93   //
     94   // If this needs to be mitigated in a production system running this code,
     95   // DexCache::kDexCacheMethodTypeCacheSize can be set to zero.
     96   MethodTypeDexCacheType* method_types = nullptr;
     97   size_t num_method_types = 0;
     98 
     99   if (dex_file->NumProtoIds() < kDexCacheMethodTypeCacheSize) {
    100     num_method_types = dex_file->NumProtoIds();
    101   } else {
    102     num_method_types = kDexCacheMethodTypeCacheSize;
    103   }
    104 
    105   if (num_method_types > 0) {
    106     method_types = reinterpret_cast<MethodTypeDexCacheType*>(
    107         raw_arrays + layout.MethodTypesOffset());
    108   }
    109 
    110   GcRoot<mirror::CallSite>* call_sites = (dex_file->NumCallSiteIds() == 0)
    111       ? nullptr
    112       : reinterpret_cast<GcRoot<CallSite>*>(raw_arrays + layout.CallSitesOffset());
    113 
    114   DCHECK_ALIGNED(raw_arrays, alignof(StringDexCacheType)) <<
    115                  "Expected raw_arrays to align to StringDexCacheType.";
    116   DCHECK_ALIGNED(layout.StringsOffset(), alignof(StringDexCacheType)) <<
    117                  "Expected StringsOffset() to align to StringDexCacheType.";
    118   DCHECK_ALIGNED(strings, alignof(StringDexCacheType)) <<
    119                  "Expected strings to align to StringDexCacheType.";
    120   static_assert(alignof(StringDexCacheType) == 8u,
    121                 "Expected StringDexCacheType to have align of 8.");
    122   if (kIsDebugBuild) {
    123     // Sanity check to make sure all the dex cache arrays are empty. b/28992179
    124     for (size_t i = 0; i < num_strings; ++i) {
    125       CHECK_EQ(strings[i].load(std::memory_order_relaxed).index, 0u);
    126       CHECK(strings[i].load(std::memory_order_relaxed).object.IsNull());
    127     }
    128     for (size_t i = 0; i < num_types; ++i) {
    129       CHECK_EQ(types[i].load(std::memory_order_relaxed).index, 0u);
    130       CHECK(types[i].load(std::memory_order_relaxed).object.IsNull());
    131     }
    132     for (size_t i = 0; i < num_methods; ++i) {
    133       CHECK_EQ(GetNativePairPtrSize(methods, i, image_pointer_size).index, 0u);
    134       CHECK(GetNativePairPtrSize(methods, i, image_pointer_size).object == nullptr);
    135     }
    136     for (size_t i = 0; i < num_fields; ++i) {
    137       CHECK_EQ(GetNativePairPtrSize(fields, i, image_pointer_size).index, 0u);
    138       CHECK(GetNativePairPtrSize(fields, i, image_pointer_size).object == nullptr);
    139     }
    140     for (size_t i = 0; i < num_method_types; ++i) {
    141       CHECK_EQ(method_types[i].load(std::memory_order_relaxed).index, 0u);
    142       CHECK(method_types[i].load(std::memory_order_relaxed).object.IsNull());
    143     }
    144     for (size_t i = 0; i < dex_file->NumCallSiteIds(); ++i) {
    145       CHECK(call_sites[i].IsNull());
    146     }
    147   }
    148   if (strings != nullptr) {
    149     mirror::StringDexCachePair::Initialize(strings);
    150   }
    151   if (types != nullptr) {
    152     mirror::TypeDexCachePair::Initialize(types);
    153   }
    154   if (fields != nullptr) {
    155     mirror::FieldDexCachePair::Initialize(fields, image_pointer_size);
    156   }
    157   if (methods != nullptr) {
    158     mirror::MethodDexCachePair::Initialize(methods, image_pointer_size);
    159   }
    160   if (method_types != nullptr) {
    161     mirror::MethodTypeDexCachePair::Initialize(method_types);
    162   }
    163   dex_cache->Init(dex_file,
    164                   location,
    165                   strings,
    166                   num_strings,
    167                   types,
    168                   num_types,
    169                   methods,
    170                   num_methods,
    171                   fields,
    172                   num_fields,
    173                   method_types,
    174                   num_method_types,
    175                   call_sites,
    176                   dex_file->NumCallSiteIds());
    177 }
    178 
    179 void DexCache::Init(const DexFile* dex_file,
    180                     ObjPtr<String> location,
    181                     StringDexCacheType* strings,
    182                     uint32_t num_strings,
    183                     TypeDexCacheType* resolved_types,
    184                     uint32_t num_resolved_types,
    185                     MethodDexCacheType* resolved_methods,
    186                     uint32_t num_resolved_methods,
    187                     FieldDexCacheType* resolved_fields,
    188                     uint32_t num_resolved_fields,
    189                     MethodTypeDexCacheType* resolved_method_types,
    190                     uint32_t num_resolved_method_types,
    191                     GcRoot<CallSite>* resolved_call_sites,
    192                     uint32_t num_resolved_call_sites) {
    193   CHECK(dex_file != nullptr);
    194   CHECK(location != nullptr);
    195   CHECK_EQ(num_strings != 0u, strings != nullptr);
    196   CHECK_EQ(num_resolved_types != 0u, resolved_types != nullptr);
    197   CHECK_EQ(num_resolved_methods != 0u, resolved_methods != nullptr);
    198   CHECK_EQ(num_resolved_fields != 0u, resolved_fields != nullptr);
    199   CHECK_EQ(num_resolved_method_types != 0u, resolved_method_types != nullptr);
    200   CHECK_EQ(num_resolved_call_sites != 0u, resolved_call_sites != nullptr);
    201 
    202   SetDexFile(dex_file);
    203   SetLocation(location);
    204   SetStrings(strings);
    205   SetResolvedTypes(resolved_types);
    206   SetResolvedMethods(resolved_methods);
    207   SetResolvedFields(resolved_fields);
    208   SetResolvedMethodTypes(resolved_method_types);
    209   SetResolvedCallSites(resolved_call_sites);
    210   SetField32<false>(NumStringsOffset(), num_strings);
    211   SetField32<false>(NumResolvedTypesOffset(), num_resolved_types);
    212   SetField32<false>(NumResolvedMethodsOffset(), num_resolved_methods);
    213   SetField32<false>(NumResolvedFieldsOffset(), num_resolved_fields);
    214   SetField32<false>(NumResolvedMethodTypesOffset(), num_resolved_method_types);
    215   SetField32<false>(NumResolvedCallSitesOffset(), num_resolved_call_sites);
    216 }
    217 
    218 void DexCache::SetLocation(ObjPtr<mirror::String> location) {
    219   SetFieldObject<false>(OFFSET_OF_OBJECT_MEMBER(DexCache, location_), location);
    220 }
    221 
    222 #if !defined(__aarch64__) && !defined(__x86_64__)
    223 static pthread_mutex_t dex_cache_slow_atomic_mutex = PTHREAD_MUTEX_INITIALIZER;
    224 
    225 DexCache::ConversionPair64 DexCache::AtomicLoadRelaxed16B(std::atomic<ConversionPair64>* target) {
    226   pthread_mutex_lock(&dex_cache_slow_atomic_mutex);
    227   DexCache::ConversionPair64 value = *reinterpret_cast<ConversionPair64*>(target);
    228   pthread_mutex_unlock(&dex_cache_slow_atomic_mutex);
    229   return value;
    230 }
    231 
    232 void DexCache::AtomicStoreRelease16B(std::atomic<ConversionPair64>* target,
    233                                      ConversionPair64 value) {
    234   pthread_mutex_lock(&dex_cache_slow_atomic_mutex);
    235   *reinterpret_cast<ConversionPair64*>(target) = value;
    236   pthread_mutex_unlock(&dex_cache_slow_atomic_mutex);
    237 }
    238 #endif
    239 
    240 }  // namespace mirror
    241 }  // namespace art
    242