summaryrefslogtreecommitdiffstats
path: root/runtime
diff options
context:
space:
mode:
authorMathieu Chartier <mathieuc@google.com>2015-06-23 00:14:43 +0000
committerAndroid (Google) Code Review <android-gerrit@google.com>2015-06-23 00:14:46 +0000
commit7c19550e66162442c1341e60578996f92dccf8ec (patch)
tree0b3e0e19187eb95809ef26ab246923a36c5eddbf /runtime
parentbad9c7b7f88689133cae59d9ccae231822a2020c (diff)
parent6e80460bdf0aa9bd273d4a4d665d679c651b5f4f (diff)
downloadandroid_art-7c19550e66162442c1341e60578996f92dccf8ec.tar.gz
android_art-7c19550e66162442c1341e60578996f92dccf8ec.tar.bz2
android_art-7c19550e66162442c1341e60578996f92dccf8ec.zip
Merge "Fix another miranda method moving GC bug" into mnc-dev
Diffstat (limited to 'runtime')
-rw-r--r--runtime/class_linker.cc38
-rw-r--r--runtime/stride_iterator.h4
2 files changed, 24 insertions, 18 deletions
diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc
index 2e97f3c909..5240447c75 100644
--- a/runtime/class_linker.cc
+++ b/runtime/class_linker.cc
@@ -4928,8 +4928,7 @@ bool ClassLinker::LinkInterfaceMethods(Thread* self, Handle<mirror::Class> klass
}
}
if (miranda_method == nullptr) {
- size_t size = ArtMethod::ObjectSize(image_pointer_size_);
- miranda_method = reinterpret_cast<ArtMethod*>(allocator.Alloc(size));
+ miranda_method = reinterpret_cast<ArtMethod*>(allocator.Alloc(method_size));
CHECK(miranda_method != nullptr);
// Point the interface table at a phantom slot.
new(miranda_method) ArtMethod(*interface_method, image_pointer_size_);
@@ -4968,34 +4967,42 @@ bool ClassLinker::LinkInterfaceMethods(Thread* self, Handle<mirror::Class> klass
++out;
}
}
+ StrideIterator<ArtMethod> out(
+ reinterpret_cast<uintptr_t>(virtuals) + old_method_count * method_size, method_size);
+ // Copy over miranda methods before copying vtable since CopyOf may cause thread suspension and
+ // we want the roots of the miranda methods to get visited.
+ for (ArtMethod* mir_method : miranda_methods) {
+ out->CopyFrom(mir_method, image_pointer_size_);
+ out->SetAccessFlags(out->GetAccessFlags() | kAccMiranda);
+ move_table.emplace(mir_method, &*out);
+ ++out;
+ }
UpdateClassVirtualMethods(klass.Get(), virtuals, new_method_count);
- // Done copying methods, they are all reachable from the class now, so we can end the no thread
+ // Done copying methods, they are all roots in the class now, so we can end the no thread
// suspension assert.
self->EndAssertNoThreadSuspension(old_cause);
- size_t old_vtable_count = vtable->GetLength();
+ const size_t old_vtable_count = vtable->GetLength();
const size_t new_vtable_count = old_vtable_count + miranda_methods.size();
+ miranda_methods.clear();
vtable.Assign(down_cast<mirror::PointerArray*>(vtable->CopyOf(self, new_vtable_count)));
if (UNLIKELY(vtable.Get() == nullptr)) {
self->AssertPendingOOMException();
return false;
}
- StrideIterator<ArtMethod> out(
+ out = StrideIterator<ArtMethod>(
reinterpret_cast<uintptr_t>(virtuals) + old_method_count * method_size, method_size);
- for (auto* mir_method : miranda_methods) {
- ArtMethod* out_method = &*out;
- out->CopyFrom(mir_method, image_pointer_size_);
+ size_t vtable_pos = old_vtable_count;
+ for (size_t i = old_method_count; i < new_method_count; ++i) {
// Leave the declaring class alone as type indices are relative to it
- out_method->SetAccessFlags(out_method->GetAccessFlags() | kAccMiranda);
- out_method->SetMethodIndex(0xFFFF & old_vtable_count);
- vtable->SetElementPtrSize(old_vtable_count, out_method, image_pointer_size_);
- move_table.emplace(mir_method, out_method);
+ out->SetMethodIndex(0xFFFF & vtable_pos);
+ vtable->SetElementPtrSize(vtable_pos, &*out, image_pointer_size_);
++out;
- ++old_vtable_count;
+ ++vtable_pos;
}
-
+ CHECK_EQ(vtable_pos, new_vtable_count);
// Update old vtable methods.
- for (size_t i = 0; i < old_vtable_count - miranda_methods.size(); ++i) {
+ for (size_t i = 0; i < old_vtable_count; ++i) {
auto* m = vtable->GetElementPtrSize<ArtMethod*>(i, image_pointer_size_);
DCHECK(m != nullptr) << PrettyClass(klass.Get());
auto it = move_table.find(m);
@@ -5006,7 +5013,6 @@ bool ClassLinker::LinkInterfaceMethods(Thread* self, Handle<mirror::Class> klass
}
}
klass->SetVTable(vtable.Get());
- CHECK_EQ(old_vtable_count, new_vtable_count);
// Go fix up all the stale miranda pointers.
for (size_t i = 0; i < ifcount; ++i) {
for (size_t j = 0, count = iftable->GetMethodArrayCount(i); j < count; ++j) {
diff --git a/runtime/stride_iterator.h b/runtime/stride_iterator.h
index 5971524d81..bd622f3709 100644
--- a/runtime/stride_iterator.h
+++ b/runtime/stride_iterator.h
@@ -22,7 +22,7 @@
namespace art {
template<typename T>
-class StrideIterator : public std::iterator<std::random_access_iterator_tag, T> {
+class StrideIterator : public std::iterator<std::forward_iterator_tag, T> {
public:
StrideIterator(const StrideIterator&) = default;
StrideIterator(StrideIterator&&) = default;
@@ -62,7 +62,7 @@ class StrideIterator : public std::iterator<std::random_access_iterator_tag, T>
private:
uintptr_t ptr_;
- const size_t stride_;
+ size_t stride_;
};
} // namespace art