summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Mathieu Chartier <mathieuc@google.com> 2016-02-01 10:34:47 -0800
committer Mathieu Chartier <mathieuc@google.com> 2016-02-01 19:58:25 -0800
commit1aa8ec2ccdd7bedb6d30d91c89f1e94ab23c4439 (patch)
tree7b2079631ed5d8350c63c7ed3f6d0393e951ce8c
parentc3cf1d2e35a45bd2e2c60fbc9c2a1a6a56dfc529 (diff)
Fix up dex cache strings stored in classes
Previously we left the image pointer instead of fixing up the pointer to the one in the BSS. This only showed up because JIT does the same as boot image, bypassing null check. Fixed a bug where oat files without embedded dex cache arrays would get their dex cache arrays corrupted. Added a non virtual class visitor for performance. Bug: 26846419 Bug: 22858531 Change-Id: I8cd0d61e440f753b4628ddb8c932eb23a0a81027
-rw-r--r--compiler/driver/compiler_driver.cc6
-rw-r--r--compiler/image_writer.cc6
-rw-r--r--runtime/class_linker.cc143
-rw-r--r--runtime/class_linker.h13
-rw-r--r--runtime/class_table-inl.h16
-rw-r--r--runtime/class_table.cc19
-rw-r--r--runtime/class_table.h17
-rw-r--r--runtime/debugger.cc2
-rw-r--r--runtime/gc/space/image_space.cc8
-rw-r--r--runtime/image.cc2
-rw-r--r--runtime/instrumentation.cc2
-rw-r--r--runtime/jit/jit.cc4
-rw-r--r--runtime/utils/dex_cache_arrays_layout-inl.h6
13 files changed, 158 insertions, 86 deletions
diff --git a/compiler/driver/compiler_driver.cc b/compiler/driver/compiler_driver.cc
index f1b745895f..6bc2a13299 100644
--- a/compiler/driver/compiler_driver.cc
+++ b/compiler/driver/compiler_driver.cc
@@ -921,7 +921,7 @@ class ResolveCatchBlockExceptionsClassVisitor : public ClassVisitor {
std::set<std::pair<uint16_t, const DexFile*>>& exceptions_to_resolve)
: exceptions_to_resolve_(exceptions_to_resolve) {}
- virtual bool Visit(mirror::Class* c) OVERRIDE SHARED_REQUIRES(Locks::mutator_lock_) {
+ virtual bool operator()(mirror::Class* c) OVERRIDE SHARED_REQUIRES(Locks::mutator_lock_) {
const auto pointer_size = Runtime::Current()->GetClassLinker()->GetImagePointerSize();
for (auto& m : c->GetMethods(pointer_size)) {
ResolveExceptionsForMethod(&m, pointer_size);
@@ -975,7 +975,7 @@ class RecordImageClassesVisitor : public ClassVisitor {
explicit RecordImageClassesVisitor(std::unordered_set<std::string>* image_classes)
: image_classes_(image_classes) {}
- bool Visit(mirror::Class* klass) OVERRIDE SHARED_REQUIRES(Locks::mutator_lock_) {
+ bool operator()(mirror::Class* klass) OVERRIDE SHARED_REQUIRES(Locks::mutator_lock_) {
std::string temp;
image_classes_->insert(klass->GetDescriptor(&temp));
return true;
@@ -1142,7 +1142,7 @@ class ClinitImageUpdate {
public:
explicit FindImageClassesVisitor(ClinitImageUpdate* data) : data_(data) {}
- bool Visit(mirror::Class* klass) OVERRIDE SHARED_REQUIRES(Locks::mutator_lock_) {
+ bool operator()(mirror::Class* klass) OVERRIDE SHARED_REQUIRES(Locks::mutator_lock_) {
std::string temp;
const char* name = klass->GetDescriptor(&temp);
if (data_->image_class_descriptors_->find(name) != data_->image_class_descriptors_->end()) {
diff --git a/compiler/image_writer.cc b/compiler/image_writer.cc
index 60dfcfb508..d63fed5257 100644
--- a/compiler/image_writer.cc
+++ b/compiler/image_writer.cc
@@ -714,7 +714,7 @@ bool ImageWriter::AllocMemory() {
class ComputeLazyFieldsForClassesVisitor : public ClassVisitor {
public:
- bool Visit(Class* c) OVERRIDE SHARED_REQUIRES(Locks::mutator_lock_) {
+ bool operator()(Class* c) OVERRIDE SHARED_REQUIRES(Locks::mutator_lock_) {
StackHandleScope<1> hs(Thread::Current());
mirror::Class::ComputeName(hs.NewHandle(c));
return true;
@@ -852,14 +852,14 @@ class NonImageClassesVisitor : public ClassVisitor {
public:
explicit NonImageClassesVisitor(ImageWriter* image_writer) : image_writer_(image_writer) {}
- bool Visit(Class* klass) OVERRIDE SHARED_REQUIRES(Locks::mutator_lock_) {
+ bool operator()(Class* klass) OVERRIDE SHARED_REQUIRES(Locks::mutator_lock_) {
if (!image_writer_->KeepClass(klass)) {
classes_to_prune_.insert(klass);
}
return true;
}
- std::unordered_set<mirror::Class*> classes_to_prune_;
+ mutable std::unordered_set<mirror::Class*> classes_to_prune_;
ImageWriter* const image_writer_;
};
diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc
index 5ef199cb60..c73949088b 100644
--- a/runtime/class_linker.cc
+++ b/runtime/class_linker.cc
@@ -1182,11 +1182,15 @@ class VerifyClassInTableArtMethodVisitor : public ArtMethodVisitor {
ClassTable* const table_;
};
-void ClassLinker::UpdateAppImageClassLoadersAndDexCaches(
+bool ClassLinker::UpdateAppImageClassLoadersAndDexCaches(
gc::space::ImageSpace* space,
Handle<mirror::ClassLoader> class_loader,
Handle<mirror::ObjectArray<mirror::DexCache>> dex_caches,
- bool added_class_table) {
+ bool added_class_table,
+ bool* out_forward_dex_cache_array,
+ std::string* out_error_msg) {
+ DCHECK(out_forward_dex_cache_array != nullptr);
+ DCHECK(out_error_msg != nullptr);
Thread* const self = Thread::Current();
gc::Heap* const heap = Runtime::Current()->GetHeap();
const ImageHeader& header = space->GetImageHeader();
@@ -1194,8 +1198,11 @@ void ClassLinker::UpdateAppImageClassLoadersAndDexCaches(
// class loader fields.
WriterMutexLock mu(self, *Locks::classlinker_classes_lock_);
ClassTable* table = InsertClassTableForClassLoader(class_loader.Get());
- // TODO: Store class table in the image to avoid manually adding the classes.
- for (int32_t i = 0, num_dex_caches = dex_caches->GetLength(); i < num_dex_caches; i++) {
+ // Dex cache array fixup is all or nothing, we must reject app images that have mixed since we
+ // rely on clobering the dex cache arrays in the image to forward to bss.
+ size_t num_dex_caches_with_bss_arrays = 0;
+ const size_t num_dex_caches = dex_caches->GetLength();
+ for (size_t i = 0; i < num_dex_caches; i++) {
mirror::DexCache* const dex_cache = dex_caches->Get(i);
const DexFile* const dex_file = dex_cache->GetDexFile();
// If the oat file expects the dex cache arrays to be in the BSS, then allocate there and
@@ -1209,22 +1216,23 @@ void ClassLinker::UpdateAppImageClassLoadersAndDexCaches(
CHECK_EQ(num_types, dex_cache->NumResolvedTypes());
CHECK_EQ(num_methods, dex_cache->NumResolvedMethods());
CHECK_EQ(num_fields, dex_cache->NumResolvedFields());
- if (dex_file->GetOatDexFile() != nullptr &&
- dex_file->GetOatDexFile()->GetDexCacheArrays() != nullptr) {
+ const OatFile::OatDexFile* oat_dex_file = dex_file->GetOatDexFile();
+ if (oat_dex_file != nullptr && oat_dex_file->GetDexCacheArrays() != nullptr) {
+ ++num_dex_caches_with_bss_arrays;
DexCacheArraysLayout layout(image_pointer_size_, dex_file);
- uint8_t* const raw_arrays = dex_file->GetOatDexFile()->GetDexCacheArrays();
- // The space is not yet visible to the GC, we can avoid the read barriers and use
- // std::copy_n.
+ 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());
}
- std::copy_n(dex_cache->GetStrings(), num_strings, strings);
+ std::copy_n(image_resolved_strings, num_strings, strings);
+ *reinterpret_cast<GcRoot<mirror::String>**>(image_resolved_strings) = strings;
dex_cache->SetStrings(strings);
}
-
if (num_types != 0u) {
GcRoot<mirror::Class>* const image_resolved_types = dex_cache->GetResolvedTypes();
GcRoot<mirror::Class>* const types =
@@ -1282,6 +1290,9 @@ void ClassLinker::UpdateAppImageClassLoadersAndDexCaches(
// Update the class loader from the one in the image class loader to the one that loaded
// the app image.
klass->SetClassLoader(class_loader.Get());
+ // The resolved type could be from another dex cache, go through the dex cache just in
+ // case.
+ klass->SetDexCacheStrings(klass->GetDexCache()->GetStrings());
// If there are multiple dex caches, there may be the same class multiple times
// in different dex caches. Check for this since inserting will add duplicates
// otherwise.
@@ -1326,7 +1337,6 @@ void ClassLinker::UpdateAppImageClassLoadersAndDexCaches(
CHECK_EQ(table->LookupByDescriptor(super_class), super_class);
}
}
- DCHECK_EQ(klass->GetClassLoader(), class_loader.Get());
if (kIsDebugBuild) {
for (ArtMethod& m : klass->GetDirectMethods(sizeof(void*))) {
const void* code = m.GetEntryPointFromQuickCompiledCode();
@@ -1354,20 +1364,66 @@ void ClassLinker::UpdateAppImageClassLoadersAndDexCaches(
}
}
}
- {
+ *out_forward_dex_cache_array = num_dex_caches_with_bss_arrays != 0;
+ if (*out_forward_dex_cache_array) {
+ if (num_dex_caches_with_bss_arrays != num_dex_caches) {
+ // Reject application image since we cannot forward only some of the dex cache arrays.
+ // TODO: We could get around this by having a dedicated forwarding slot. It should be an
+ // uncommon case.
+ *out_error_msg = StringPrintf("Dex caches in bss does not match total: %zu vs %zu",
+ num_dex_caches_with_bss_arrays,
+ num_dex_caches);
+ return false;
+ }
FixupArtMethodArrayVisitor visitor(header);
header.GetImageSection(ImageHeader::kSectionArtMethods).VisitPackedArtMethods(
- &visitor, space->Begin(), sizeof(void*));
+ &visitor,
+ space->Begin(),
+ sizeof(void*));
Runtime::Current()->GetHeap()->WriteBarrierEveryFieldOf(class_loader.Get());
}
if (kIsDebugBuild) {
ClassTable* const class_table = class_loader.Get()->GetClassTable();
VerifyClassInTableArtMethodVisitor visitor2(class_table);
header.GetImageSection(ImageHeader::kSectionArtMethods).VisitPackedArtMethods(
- &visitor2, space->Begin(), sizeof(void*));
+ &visitor2,
+ space->Begin(),
+ sizeof(void*));
}
+ return true;
}
+class UpdateClassLoaderAndResolvedStringsVisitor {
+ public:
+ UpdateClassLoaderAndResolvedStringsVisitor(gc::space::ImageSpace* space,
+ mirror::ClassLoader* class_loader,
+ bool forward_strings)
+ : space_(space),
+ class_loader_(class_loader),
+ forward_strings_(forward_strings) {}
+
+ bool operator()(mirror::Class* klass) const SHARED_REQUIRES(Locks::mutator_lock_) {
+ if (forward_strings_) {
+ GcRoot<mirror::String>* 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";
+ GcRoot<mirror::String>* new_strings = *reinterpret_cast<GcRoot<mirror::String>**>(strings);
+ DCHECK_NE(strings, new_strings);
+ klass->SetDexCacheStrings(new_strings);
+ }
+ }
+ // Finally, update class loader.
+ klass->SetClassLoader(class_loader_);
+ return true;
+ }
+
+ gc::space::ImageSpace* const space_;
+ mirror::ClassLoader* const class_loader_;
+ const bool forward_strings_;
+};
+
bool ClassLinker::AddImageSpace(
gc::space::ImageSpace* space,
Handle<mirror::ClassLoader> class_loader,
@@ -1576,21 +1632,39 @@ bool ClassLinker::AddImageSpace(
if (app_image) {
GetOrCreateAllocatorForClassLoader(class_loader.Get()); // Make sure we have a linear alloc.
}
- if (class_table_section.Size() > 0u) {
- const uint64_t start_time2 = NanoTime();
+ ClassTable* class_table = nullptr;
+ {
WriterMutexLock mu(self, *Locks::classlinker_classes_lock_);
- ClassTable* const class_table = InsertClassTableForClassLoader(class_loader.Get());
- class_table->ReadFromMemory(space->Begin() + class_table_section.Offset());
- if (app_image) {
- class_table->SetClassLoader(class_loader.Get());
- } else {
- dex_cache_boot_image_class_lookup_required_ = false;
+ class_table = InsertClassTableForClassLoader(class_loader.Get());
+ if (class_table_section.Size() > 0u) {
+ const uint64_t start_time2 = NanoTime();
+ class_table->ReadFromMemory(space->Begin() + class_table_section.Offset());
+ if (!app_image) {
+ dex_cache_boot_image_class_lookup_required_ = false;
+ }
+ VLOG(image) << "Adding class table classes took " << PrettyDuration(NanoTime() - start_time2);
+ added_class_table = true;
}
- VLOG(image) << "Adding class table classes took " << PrettyDuration(NanoTime() - start_time2);
- added_class_table = true;
}
if (app_image) {
- UpdateAppImageClassLoadersAndDexCaches(space, class_loader, dex_caches, added_class_table);
+ bool forward_dex_cache_arrays = false;
+ if (!UpdateAppImageClassLoadersAndDexCaches(space,
+ class_loader,
+ dex_caches,
+ added_class_table,
+ /*out*/&forward_dex_cache_arrays,
+ /*out*/error_msg)) {
+ return false;
+ }
+ if (added_class_table) {
+ WriterMutexLock mu(self, *Locks::classlinker_classes_lock_);
+ // Update class loader and resolved strings. If added_class_table is false, the resolved
+ // strings were already updated in UpdateAppImageClassLoadersAndDexCaches.
+ UpdateClassLoaderAndResolvedStringsVisitor visitor(space,
+ class_loader.Get(),
+ forward_dex_cache_arrays);
+ class_table->Visit(visitor);
+ }
}
VLOG(class_linker) << "Adding image space took " << PrettyDuration(NanoTime() - start_time);
return true;
@@ -1677,7 +1751,7 @@ class VisitClassLoaderClassesVisitor : public ClassLoaderVisitor {
void Visit(mirror::ClassLoader* class_loader)
SHARED_REQUIRES(Locks::classlinker_classes_lock_, Locks::mutator_lock_) OVERRIDE {
ClassTable* const class_table = class_loader->GetClassTable();
- if (!done_ && class_table != nullptr && !class_table->Visit(visitor_)) {
+ if (!done_ && class_table != nullptr && !class_table->Visit(*visitor_)) {
// If the visitor ClassTable returns false it means that we don't need to continue.
done_ = true;
}
@@ -1690,7 +1764,7 @@ class VisitClassLoaderClassesVisitor : public ClassLoaderVisitor {
};
void ClassLinker::VisitClassesInternal(ClassVisitor* visitor) {
- if (boot_class_table_.Visit(visitor)) {
+ if (boot_class_table_.Visit(*visitor)) {
VisitClassLoaderClassesVisitor loader_visitor(visitor);
VisitClassLoaders(&loader_visitor);
}
@@ -1713,7 +1787,7 @@ void ClassLinker::VisitClasses(ClassVisitor* visitor) {
class GetClassesInToVector : public ClassVisitor {
public:
- bool Visit(mirror::Class* klass) OVERRIDE {
+ bool operator()(mirror::Class* klass) OVERRIDE {
classes_.push_back(klass);
return true;
}
@@ -1725,7 +1799,7 @@ class GetClassInToObjectArray : public ClassVisitor {
explicit GetClassInToObjectArray(mirror::ObjectArray<mirror::Class>* arr)
: arr_(arr), index_(0) {}
- bool Visit(mirror::Class* klass) OVERRIDE SHARED_REQUIRES(Locks::mutator_lock_) {
+ bool operator()(mirror::Class* klass) OVERRIDE SHARED_REQUIRES(Locks::mutator_lock_) {
++index_;
if (index_ <= arr_->GetLength()) {
arr_->Set(index_ - 1, klass);
@@ -1746,16 +1820,17 @@ class GetClassInToObjectArray : public ClassVisitor {
void ClassLinker::VisitClassesWithoutClassesLock(ClassVisitor* visitor) {
// TODO: it may be possible to avoid secondary storage if we iterate over dex caches. The problem
// is avoiding duplicates.
+ Thread* const self = Thread::Current();
if (!kMovingClasses) {
+ ScopedAssertNoThreadSuspension nts(self, __FUNCTION__);
GetClassesInToVector accumulator;
VisitClasses(&accumulator);
for (mirror::Class* klass : accumulator.classes_) {
- if (!visitor->Visit(klass)) {
+ if (!visitor->operator()(klass)) {
return;
}
}
} else {
- Thread* const self = Thread::Current();
StackHandleScope<1> hs(self);
auto classes = hs.NewHandle<mirror::ObjectArray<mirror::Class>>(nullptr);
// We size the array assuming classes won't be added to the class table during the visit.
@@ -1783,7 +1858,7 @@ void ClassLinker::VisitClassesWithoutClassesLock(ClassVisitor* visitor) {
// the class table grew then the loop repeats. If classes are created after the loop has
// finished then we don't visit.
mirror::Class* klass = classes->Get(i);
- if (klass != nullptr && !visitor->Visit(klass)) {
+ if (klass != nullptr && !visitor->operator()(klass)) {
return;
}
}
@@ -7157,7 +7232,7 @@ class DumpClassVisitor : public ClassVisitor {
public:
explicit DumpClassVisitor(int flags) : flags_(flags) {}
- bool Visit(mirror::Class* klass) OVERRIDE SHARED_REQUIRES(Locks::mutator_lock_) {
+ bool operator()(mirror::Class* klass) OVERRIDE SHARED_REQUIRES(Locks::mutator_lock_) {
klass->DumpClass(LOG(ERROR), flags_);
return true;
}
diff --git a/runtime/class_linker.h b/runtime/class_linker.h
index 5176cbd3ea..9217c32fe7 100644
--- a/runtime/class_linker.h
+++ b/runtime/class_linker.h
@@ -60,6 +60,13 @@ template<size_t kNumReferences> class PACKED(4) StackHandleScope;
enum VisitRootFlags : uint8_t;
+class ClassVisitor {
+ public:
+ virtual ~ClassVisitor() {}
+ // Return true to continue visiting.
+ virtual bool operator()(mirror::Class* klass) = 0;
+};
+
class ClassLoaderVisitor {
public:
virtual ~ClassLoaderVisitor() {}
@@ -1007,11 +1014,13 @@ class ClassLinker {
SHARED_REQUIRES(Locks::mutator_lock_)
REQUIRES(!Locks::classlinker_classes_lock_);
- void UpdateAppImageClassLoadersAndDexCaches(
+ bool UpdateAppImageClassLoadersAndDexCaches(
gc::space::ImageSpace* space,
Handle<mirror::ClassLoader> class_loader,
Handle<mirror::ObjectArray<mirror::DexCache>> dex_caches,
- bool added_class_table)
+ bool added_class_table,
+ bool* out_forward_dex_cache_array,
+ std::string* out_error_msg)
REQUIRES(!dex_lock_)
SHARED_REQUIRES(Locks::mutator_lock_);
diff --git a/runtime/class_table-inl.h b/runtime/class_table-inl.h
index aef02b6d5d..e512906507 100644
--- a/runtime/class_table-inl.h
+++ b/runtime/class_table-inl.h
@@ -28,6 +28,9 @@ void ClassTable::VisitRoots(Visitor& visitor) {
visitor.VisitRoot(root.AddressWithoutBarrier());
}
}
+ for (GcRoot<mirror::Object>& root : dex_files_) {
+ visitor.VisitRoot(root.AddressWithoutBarrier());
+ }
}
template<class Visitor>
@@ -42,6 +45,19 @@ void ClassTable::VisitRoots(const Visitor& visitor) {
}
}
+template <typename Visitor>
+bool ClassTable::Visit(Visitor& visitor) {
+ for (ClassSet& class_set : classes_) {
+ for (GcRoot<mirror::Class>& root : class_set) {
+ if (!visitor(root.Read())) {
+ return false;
+ }
+ }
+ }
+ return true;
+}
+
+
} // namespace art
#endif // ART_RUNTIME_CLASS_TABLE_INL_H_
diff --git a/runtime/class_table.cc b/runtime/class_table.cc
index 2a4f0e01af..afb0556e1e 100644
--- a/runtime/class_table.cc
+++ b/runtime/class_table.cc
@@ -73,17 +73,6 @@ mirror::Class* ClassTable::UpdateClass(const char* descriptor, mirror::Class* kl
return existing;
}
-bool ClassTable::Visit(ClassVisitor* visitor) {
- for (ClassSet& class_set : classes_) {
- for (GcRoot<mirror::Class>& root : class_set) {
- if (!visitor->Visit(root.Read())) {
- return false;
- }
- }
- }
- return true;
-}
-
size_t ClassTable::NumZygoteClasses() const {
size_t sum = 0;
for (size_t i = 0; i < classes_.size() - 1; ++i) {
@@ -183,12 +172,4 @@ size_t ClassTable::ReadFromMemory(uint8_t* ptr) {
return read_count;
}
-void ClassTable::SetClassLoader(mirror::ClassLoader* class_loader) {
- for (const ClassSet& class_set : classes_) {
- for (const GcRoot<mirror::Class>& root : class_set) {
- root.Read()->SetClassLoader(class_loader);
- }
- }
-}
-
} // namespace art
diff --git a/runtime/class_table.h b/runtime/class_table.h
index 0b420352c3..5f2eb48d55 100644
--- a/runtime/class_table.h
+++ b/runtime/class_table.h
@@ -36,13 +36,6 @@ namespace mirror {
class ClassLoader;
} // namespace mirror
-class ClassVisitor {
- public:
- virtual ~ClassVisitor() {}
- // Return true to continue visiting.
- virtual bool Visit(mirror::Class* klass) = 0;
-};
-
// Each loader has a ClassTable
class ClassTable {
public:
@@ -80,8 +73,9 @@ class ClassTable {
NO_THREAD_SAFETY_ANALYSIS
SHARED_REQUIRES(Locks::classlinker_classes_lock_, Locks::mutator_lock_);
- // Return false if the callback told us to exit.
- bool Visit(ClassVisitor* visitor)
+ // Stops visit if the visitor returns false.
+ template <typename Visitor>
+ bool Visit(Visitor& visitor)
SHARED_REQUIRES(Locks::classlinker_classes_lock_, Locks::mutator_lock_);
// Return the first class that matches the descriptor. Returns null if there are none.
@@ -118,11 +112,6 @@ class ClassTable {
REQUIRES(Locks::classlinker_classes_lock_)
SHARED_REQUIRES(Locks::mutator_lock_);
- // Change the class loader of all the contained classes.
- void SetClassLoader(mirror::ClassLoader* class_loader)
- REQUIRES(Locks::classlinker_classes_lock_)
- SHARED_REQUIRES(Locks::mutator_lock_);
-
private:
class ClassDescriptorHashEquals {
public:
diff --git a/runtime/debugger.cc b/runtime/debugger.cc
index a0f875d6b8..904490aa8c 100644
--- a/runtime/debugger.cc
+++ b/runtime/debugger.cc
@@ -983,7 +983,7 @@ class ClassListCreator : public ClassVisitor {
public:
explicit ClassListCreator(std::vector<JDWP::RefTypeId>* classes) : classes_(classes) {}
- bool Visit(mirror::Class* c) OVERRIDE SHARED_REQUIRES(Locks::mutator_lock_) {
+ bool operator()(mirror::Class* c) OVERRIDE SHARED_REQUIRES(Locks::mutator_lock_) {
if (!c->IsPrimitive()) {
classes_->push_back(Dbg::GetObjectRegistry()->AddRefType(c));
}
diff --git a/runtime/gc/space/image_space.cc b/runtime/gc/space/image_space.cc
index 998db5271a..08b1a0090d 100644
--- a/runtime/gc/space/image_space.cc
+++ b/runtime/gc/space/image_space.cc
@@ -1047,7 +1047,7 @@ static bool RelocateInPlace(ImageHeader& image_header,
if (strings != nullptr) {
GcRoot<mirror::String>* new_strings = fixup_adapter.ForwardObject(strings);
if (strings != new_strings) {
- dex_cache->SetFieldPtr64<false>(mirror::DexCache::StringsOffset(), new_strings);
+ dex_cache->SetStrings(new_strings);
}
dex_cache->FixupStrings<kWithoutReadBarrier>(new_strings, fixup_adapter);
}
@@ -1055,7 +1055,7 @@ static bool RelocateInPlace(ImageHeader& image_header,
if (types != nullptr) {
GcRoot<mirror::Class>* new_types = fixup_adapter.ForwardObject(types);
if (types != new_types) {
- dex_cache->SetFieldPtr64<false>(mirror::DexCache::ResolvedTypesOffset(), new_types);
+ dex_cache->SetResolvedTypes(new_types);
}
dex_cache->FixupResolvedTypes<kWithoutReadBarrier>(new_types, fixup_adapter);
}
@@ -1063,7 +1063,7 @@ static bool RelocateInPlace(ImageHeader& image_header,
if (methods != nullptr) {
ArtMethod** new_methods = fixup_adapter.ForwardObject(methods);
if (methods != new_methods) {
- dex_cache->SetFieldPtr64<false>(mirror::DexCache::ResolvedMethodsOffset(), new_methods);
+ dex_cache->SetResolvedMethods(new_methods);
}
for (size_t j = 0, num = dex_cache->NumResolvedMethods(); j != num; ++j) {
ArtMethod* orig = mirror::DexCache::GetElementPtrSize(new_methods, j, sizeof(void*));
@@ -1077,7 +1077,7 @@ static bool RelocateInPlace(ImageHeader& image_header,
if (fields != nullptr) {
ArtField** new_fields = fixup_adapter.ForwardObject(fields);
if (fields != new_fields) {
- dex_cache->SetFieldPtr64<false>(mirror::DexCache::ResolvedFieldsOffset(), new_fields);
+ dex_cache->SetResolvedFields(new_fields);
}
for (size_t j = 0, num = dex_cache->NumResolvedFields(); j != num; ++j) {
ArtField* orig = mirror::DexCache::GetElementPtrSize(new_fields, j, sizeof(void*));
diff --git a/runtime/image.cc b/runtime/image.cc
index de00343451..1f54e3e6ae 100644
--- a/runtime/image.cc
+++ b/runtime/image.cc
@@ -24,7 +24,7 @@
namespace art {
const uint8_t ImageHeader::kImageMagic[] = { 'a', 'r', 't', '\n' };
-const uint8_t ImageHeader::kImageVersion[] = { '0', '2', '6', '\0' };
+const uint8_t ImageHeader::kImageVersion[] = { '0', '2', '7', '\0' };
ImageHeader::ImageHeader(uint32_t image_begin,
uint32_t image_size,
diff --git a/runtime/instrumentation.cc b/runtime/instrumentation.cc
index c57b1bbf2d..748463529e 100644
--- a/runtime/instrumentation.cc
+++ b/runtime/instrumentation.cc
@@ -55,7 +55,7 @@ class InstallStubsClassVisitor : public ClassVisitor {
explicit InstallStubsClassVisitor(Instrumentation* instrumentation)
: instrumentation_(instrumentation) {}
- bool Visit(mirror::Class* klass) OVERRIDE REQUIRES(Locks::mutator_lock_) {
+ bool operator()(mirror::Class* klass) OVERRIDE REQUIRES(Locks::mutator_lock_) {
instrumentation_->InstallStubsForClass(klass);
return true; // we visit all classes.
}
diff --git a/runtime/jit/jit.cc b/runtime/jit/jit.cc
index 4e0146c603..b7111815e4 100644
--- a/runtime/jit/jit.cc
+++ b/runtime/jit/jit.cc
@@ -239,11 +239,11 @@ void Jit::NewTypeLoadedIfUsingJit(mirror::Class* type) {
void Jit::DumpTypeInfoForLoadedTypes(ClassLinker* linker) {
struct CollectClasses : public ClassVisitor {
- bool Visit(mirror::Class* klass) override {
+ bool operator()(mirror::Class* klass) override {
classes_.push_back(klass);
return true;
}
- std::vector<mirror::Class*> classes_;
+ mutable std::vector<mirror::Class*> classes_;
};
if (generate_debug_info_) {
diff --git a/runtime/utils/dex_cache_arrays_layout-inl.h b/runtime/utils/dex_cache_arrays_layout-inl.h
index f6ee6a2b1a..d63083c5c4 100644
--- a/runtime/utils/dex_cache_arrays_layout-inl.h
+++ b/runtime/utils/dex_cache_arrays_layout-inl.h
@@ -87,11 +87,13 @@ inline size_t DexCacheArraysLayout::StringOffset(uint32_t string_idx) const {
}
inline size_t DexCacheArraysLayout::StringsSize(size_t num_elements) const {
- return ArraySize(sizeof(GcRoot<mirror::String>), num_elements);
+ // App image patching relies on having enough room for a forwarding pointer in the types array.
+ return std::max(ArraySize(sizeof(GcRoot<mirror::String>), num_elements), pointer_size_);
}
inline size_t DexCacheArraysLayout::StringsAlignment() const {
- return alignof(GcRoot<mirror::String>);
+ // App image patching relies on having enough room for a forwarding pointer in the strings array.
+ return pointer_size_;
}
inline size_t DexCacheArraysLayout::FieldOffset(uint32_t field_idx) const {