summaryrefslogtreecommitdiff
path: root/runtime/class_linker.cc
diff options
context:
space:
mode:
Diffstat (limited to 'runtime/class_linker.cc')
-rw-r--r--runtime/class_linker.cc56
1 files changed, 39 insertions, 17 deletions
diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc
index 4d48da6a83..f4400c3de1 100644
--- a/runtime/class_linker.cc
+++ b/runtime/class_linker.cc
@@ -66,6 +66,7 @@
#include "mirror/class.h"
#include "mirror/class-inl.h"
#include "mirror/class_loader.h"
+#include "mirror/dex_cache.h"
#include "mirror/dex_cache-inl.h"
#include "mirror/field.h"
#include "mirror/iftable-inl.h"
@@ -1271,7 +1272,10 @@ bool ClassLinker::UpdateAppImageClassLoadersAndDexCaches(
// If the oat file expects the dex cache arrays to be in the BSS, then allocate there and
// copy over the arrays.
DCHECK(dex_file != nullptr);
- const size_t num_strings = dex_file->NumStringIds();
+ size_t num_strings = mirror::DexCache::kDexCacheStringCacheSize;
+ if (dex_file->NumStringIds() < num_strings) {
+ num_strings = dex_file->NumStringIds();
+ }
const size_t num_types = dex_file->NumTypeIds();
const size_t num_methods = dex_file->NumMethodIds();
const size_t num_fields = dex_file->NumFieldIds();
@@ -1281,16 +1285,17 @@ bool ClassLinker::UpdateAppImageClassLoadersAndDexCaches(
CHECK_EQ(num_fields, dex_cache->NumResolvedFields());
DexCacheArraysLayout layout(image_pointer_size_, dex_file);
uint8_t* const raw_arrays = oat_dex_file->GetDexCacheArrays();
- // The space is not yet visible to the GC, we can avoid the read barriers and use
- // std::copy_n.
if (num_strings != 0u) {
- GcRoot<mirror::String>* const image_resolved_strings = dex_cache->GetStrings();
- GcRoot<mirror::String>* const strings =
- reinterpret_cast<GcRoot<mirror::String>*>(raw_arrays + layout.StringsOffset());
- for (size_t j = 0; kIsDebugBuild && j < num_strings; ++j) {
- DCHECK(strings[j].IsNull());
+ mirror::StringDexCacheType* const image_resolved_strings = dex_cache->GetStrings();
+ mirror::StringDexCacheType* const strings =
+ reinterpret_cast<mirror::StringDexCacheType*>(raw_arrays + layout.StringsOffset());
+ for (size_t j = 0; j < num_strings; ++j) {
+ DCHECK_EQ(strings[j].load(std::memory_order_relaxed).string_index, 0u);
+ DCHECK(strings[j].load(std::memory_order_relaxed).string_pointer.IsNull());
+ strings[j].store(image_resolved_strings[j].load(std::memory_order_relaxed),
+ std::memory_order_relaxed);
}
- std::copy_n(image_resolved_strings, num_strings, strings);
+ mirror::StringDexCachePair::Initialize(strings);
dex_cache->SetStrings(strings);
}
if (num_types != 0u) {
@@ -1473,14 +1478,14 @@ class UpdateClassLoaderAndResolvedStringsVisitor {
bool operator()(mirror::Class* klass) const SHARED_REQUIRES(Locks::mutator_lock_) {
if (forward_strings_) {
- GcRoot<mirror::String>* strings = klass->GetDexCacheStrings();
+ mirror::StringDexCacheType* strings = klass->GetDexCacheStrings();
if (strings != nullptr) {
DCHECK(
space_->GetImageHeader().GetImageSection(ImageHeader::kSectionDexCacheArrays).Contains(
reinterpret_cast<uint8_t*>(strings) - space_->Begin()))
<< "String dex cache array for " << PrettyClass(klass) << " is not in app image";
// Dex caches have already been updated, so take the strings pointer from there.
- GcRoot<mirror::String>* new_strings = klass->GetDexCache()->GetStrings();
+ mirror::StringDexCacheType* new_strings = klass->GetDexCache()->GetStrings();
DCHECK_NE(strings, new_strings);
klass->SetDexCacheStrings(new_strings);
}
@@ -2079,18 +2084,31 @@ mirror::DexCache* ClassLinker::AllocDexCache(Thread* self,
// Zero-initialized.
raw_arrays = reinterpret_cast<uint8_t*>(linear_alloc->Alloc(self, layout.Size()));
}
- GcRoot<mirror::String>* strings = (dex_file.NumStringIds() == 0u) ? nullptr :
- reinterpret_cast<GcRoot<mirror::String>*>(raw_arrays + layout.StringsOffset());
+ 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();
+ }
+ 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 < dex_file.NumStringIds(); ++i) {
- CHECK(strings[i].Read<kWithoutReadBarrier>() == nullptr);
+ for (size_t i = 0; i < num_strings; ++i) {
+ CHECK_EQ(strings[i].load(std::memory_order_relaxed).string_index, 0u);
+ CHECK(strings[i].load(std::memory_order_relaxed).string_pointer.IsNull());
}
for (size_t i = 0; i < dex_file.NumTypeIds(); ++i) {
CHECK(types[i].Read<kWithoutReadBarrier>() == nullptr);
@@ -2102,10 +2120,13 @@ mirror::DexCache* ClassLinker::AllocDexCache(Thread* self,
CHECK(mirror::DexCache::GetElementPtrSize(fields, i, image_pointer_size_) == nullptr);
}
}
+ if (strings != nullptr) {
+ mirror::StringDexCachePair::Initialize(strings);
+ }
dex_cache->Init(&dex_file,
location.Get(),
strings,
- dex_file.NumStringIds(),
+ num_strings,
types,
dex_file.NumTypeIds(),
methods,
@@ -4525,7 +4546,8 @@ bool ClassLinker::InitializeClass(Thread* self, Handle<mirror::Class> klass,
}
self->AllowThreadSuspension();
- CHECK_EQ(klass->GetStatus(), mirror::Class::kStatusVerified) << PrettyClass(klass.Get());
+ CHECK_EQ(klass->GetStatus(), mirror::Class::kStatusVerified) << PrettyClass(klass.Get())
+ << " self.tid=" << self->GetTid() << " clinit.tid=" << klass->GetClinitThreadId();
// From here out other threads may observe that we're initializing and so changes of state
// require the a notification.