diff options
| author | 2016-12-03 01:20:05 +0000 | |
|---|---|---|
| committer | 2016-12-03 01:20:06 +0000 | |
| commit | 0480523e01102e40a072d266e43a18a0ca4344e4 (patch) | |
| tree | 3d38b5a98764fd99d6c5de1a6e9c9509168baef4 /runtime/mirror/dex_cache.cc | |
| parent | b487af4fc80ffabe0219657a9690be1316dab8e7 (diff) | |
| parent | cc1b5357f83f0b787d51fbfde3fe870c8a2fa050 (diff) | |
Merge "ART: Clean up ClassLinker"
Diffstat (limited to 'runtime/mirror/dex_cache.cc')
| -rw-r--r-- | runtime/mirror/dex_cache.cc | 108 |
1 files changed, 108 insertions, 0 deletions
diff --git a/runtime/mirror/dex_cache.cc b/runtime/mirror/dex_cache.cc index a32d51fbef..741cf3bb47 100644 --- a/runtime/mirror/dex_cache.cc +++ b/runtime/mirror/dex_cache.cc @@ -22,15 +22,123 @@ #include "gc/accounting/card_table-inl.h" #include "gc/heap.h" #include "globals.h" +#include "linear_alloc.h" #include "object.h" #include "object-inl.h" #include "object_array-inl.h" #include "runtime.h" #include "string.h" +#include "thread.h" +#include "utils/dex_cache_arrays_layout-inl.h" namespace art { namespace mirror { +void DexCache::InitializeDexCache(Thread* self, + ObjPtr<mirror::DexCache> dex_cache, + ObjPtr<mirror::String> location, + const DexFile* dex_file, + LinearAlloc* linear_alloc, + PointerSize image_pointer_size) { + DCHECK(dex_file != nullptr); + ScopedAssertNoThreadSuspension sants(__FUNCTION__); + DexCacheArraysLayout layout(image_pointer_size, dex_file); + uint8_t* raw_arrays = nullptr; + + const OatDexFile* const oat_dex = dex_file->GetOatDexFile(); + if (oat_dex != nullptr && oat_dex->GetDexCacheArrays() != nullptr) { + raw_arrays = oat_dex->GetDexCacheArrays(); + } else if (dex_file->NumStringIds() != 0u || + dex_file->NumTypeIds() != 0u || + dex_file->NumMethodIds() != 0u || + dex_file->NumFieldIds() != 0u) { + // Zero-initialized. + raw_arrays = reinterpret_cast<uint8_t*>(linear_alloc->Alloc(self, layout.Size())); + } + + mirror::StringDexCacheType* strings = (dex_file->NumStringIds() == 0u) ? nullptr : + reinterpret_cast<mirror::StringDexCacheType*>(raw_arrays + layout.StringsOffset()); + GcRoot<mirror::Class>* types = (dex_file->NumTypeIds() == 0u) ? nullptr : + reinterpret_cast<GcRoot<mirror::Class>*>(raw_arrays + layout.TypesOffset()); + ArtMethod** methods = (dex_file->NumMethodIds() == 0u) ? nullptr : + reinterpret_cast<ArtMethod**>(raw_arrays + layout.MethodsOffset()); + ArtField** fields = (dex_file->NumFieldIds() == 0u) ? nullptr : + reinterpret_cast<ArtField**>(raw_arrays + layout.FieldsOffset()); + + size_t num_strings = mirror::DexCache::kDexCacheStringCacheSize; + if (dex_file->NumStringIds() < num_strings) { + num_strings = dex_file->NumStringIds(); + } + + // Note that we allocate the method type dex caches regardless of this flag, + // and we make sure here that they're not used by the runtime. This is in the + // interest of simplicity and to avoid extensive compiler and layout class changes. + // + // If this needs to be mitigated in a production system running this code, + // DexCache::kDexCacheMethodTypeCacheSize can be set to zero. + mirror::MethodTypeDexCacheType* method_types = nullptr; + size_t num_method_types = 0; + + if (dex_file->NumProtoIds() < mirror::DexCache::kDexCacheMethodTypeCacheSize) { + num_method_types = dex_file->NumProtoIds(); + } else { + num_method_types = mirror::DexCache::kDexCacheMethodTypeCacheSize; + } + + if (num_method_types > 0) { + method_types = reinterpret_cast<mirror::MethodTypeDexCacheType*>( + raw_arrays + layout.MethodTypesOffset()); + } + + DCHECK_ALIGNED(raw_arrays, alignof(mirror::StringDexCacheType)) << + "Expected raw_arrays to align to StringDexCacheType."; + DCHECK_ALIGNED(layout.StringsOffset(), alignof(mirror::StringDexCacheType)) << + "Expected StringsOffset() to align to StringDexCacheType."; + DCHECK_ALIGNED(strings, alignof(mirror::StringDexCacheType)) << + "Expected strings to align to StringDexCacheType."; + static_assert(alignof(mirror::StringDexCacheType) == 8u, + "Expected StringDexCacheType to have align of 8."); + if (kIsDebugBuild) { + // Sanity check to make sure all the dex cache arrays are empty. b/28992179 + for (size_t i = 0; i < num_strings; ++i) { + CHECK_EQ(strings[i].load(std::memory_order_relaxed).index, 0u); + CHECK(strings[i].load(std::memory_order_relaxed).object.IsNull()); + } + for (size_t i = 0; i < dex_file->NumTypeIds(); ++i) { + CHECK(types[i].IsNull()); + } + for (size_t i = 0; i < dex_file->NumMethodIds(); ++i) { + CHECK(mirror::DexCache::GetElementPtrSize(methods, i, image_pointer_size) == nullptr); + } + for (size_t i = 0; i < dex_file->NumFieldIds(); ++i) { + CHECK(mirror::DexCache::GetElementPtrSize(fields, i, image_pointer_size) == nullptr); + } + for (size_t i = 0; i < num_method_types; ++i) { + CHECK_EQ(method_types[i].load(std::memory_order_relaxed).index, 0u); + CHECK(method_types[i].load(std::memory_order_relaxed).object.IsNull()); + } + } + if (strings != nullptr) { + mirror::StringDexCachePair::Initialize(strings); + } + if (method_types != nullptr) { + mirror::MethodTypeDexCachePair::Initialize(method_types); + } + dex_cache->Init(dex_file, + location, + strings, + num_strings, + types, + dex_file->NumTypeIds(), + methods, + dex_file->NumMethodIds(), + fields, + dex_file->NumFieldIds(), + method_types, + num_method_types, + image_pointer_size); +} + void DexCache::Init(const DexFile* dex_file, ObjPtr<String> location, StringDexCacheType* strings, |