summaryrefslogtreecommitdiffstats
path: root/runtime/mirror
diff options
context:
space:
mode:
authorHiroshi Yamauchi <yamauchi@google.com>2015-03-18 17:20:11 -0700
committerHiroshi Yamauchi <yamauchi@google.com>2015-03-19 11:48:24 -0700
commit5b783e66b26b7b6ee13d344f4b77f6b7c47c4723 (patch)
treee1f54fec55617c757813ab11beb9072521427596 /runtime/mirror
parentb63ff273375c488fae2555fad4e5873d3613aa5d (diff)
downloadart-5b783e66b26b7b6ee13d344f4b77f6b7c47c4723.tar.gz
art-5b783e66b26b7b6ee13d344f4b77f6b7c47c4723.tar.bz2
art-5b783e66b26b7b6ee13d344f4b77f6b7c47c4723.zip
Fix 003-omnibus-opcodes flaky failures with GSS GC.
Fix a moving GC bug in Class::SetStatus(). Bug: 19828874 Change-Id: I6bef49a7ce964e8a7e316f282aaf1b8544efe76d
Diffstat (limited to 'runtime/mirror')
-rw-r--r--runtime/mirror/class.cc42
-rw-r--r--runtime/mirror/class.h4
2 files changed, 25 insertions, 21 deletions
diff --git a/runtime/mirror/class.cc b/runtime/mirror/class.cc
index 6f4ef60e85..9fa6073698 100644
--- a/runtime/mirror/class.cc
+++ b/runtime/mirror/class.cc
@@ -55,26 +55,27 @@ void Class::VisitRoots(RootCallback* callback, void* arg) {
java_lang_Class_.VisitRootIfNonNull(callback, arg, RootInfo(kRootStickyClass));
}
-void Class::SetStatus(Status new_status, Thread* self) {
- Status old_status = GetStatus();
+void Class::SetStatus(Handle<Class> h_this, Status new_status, Thread* self) {
+ Status old_status = h_this->GetStatus();
ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
bool class_linker_initialized = class_linker != nullptr && class_linker->IsInitialized();
if (LIKELY(class_linker_initialized)) {
if (UNLIKELY(new_status <= old_status && new_status != kStatusError &&
new_status != kStatusRetired)) {
- LOG(FATAL) << "Unexpected change back of class status for " << PrettyClass(this) << " "
- << old_status << " -> " << new_status;
+ LOG(FATAL) << "Unexpected change back of class status for " << PrettyClass(h_this.Get())
+ << " " << old_status << " -> " << new_status;
}
if (new_status >= kStatusResolved || old_status >= kStatusResolved) {
// When classes are being resolved the resolution code should hold the lock.
- CHECK_EQ(GetLockOwnerThreadId(), self->GetThreadId())
+ CHECK_EQ(h_this->GetLockOwnerThreadId(), self->GetThreadId())
<< "Attempt to change status of class while not holding its lock: "
- << PrettyClass(this) << " " << old_status << " -> " << new_status;
+ << PrettyClass(h_this.Get()) << " " << old_status << " -> " << new_status;
}
}
if (UNLIKELY(new_status == kStatusError)) {
- CHECK_NE(GetStatus(), kStatusError)
- << "Attempt to set as erroneous an already erroneous class " << PrettyClass(this);
+ CHECK_NE(h_this->GetStatus(), kStatusError)
+ << "Attempt to set as erroneous an already erroneous class "
+ << PrettyClass(h_this.Get());
// Stash current exception.
StackHandleScope<1> hs(self);
@@ -100,7 +101,7 @@ void Class::SetStatus(Status new_status, Thread* self) {
// case.
Class* exception_class = old_exception->GetClass();
if (!eiie_class->IsAssignableFrom(exception_class)) {
- SetVerifyErrorClass(exception_class);
+ h_this->SetVerifyErrorClass(exception_class);
}
}
@@ -109,9 +110,9 @@ void Class::SetStatus(Status new_status, Thread* self) {
}
static_assert(sizeof(Status) == sizeof(uint32_t), "Size of status not equal to uint32");
if (Runtime::Current()->IsActiveTransaction()) {
- SetField32Volatile<true>(OFFSET_OF_OBJECT_MEMBER(Class, status_), new_status);
+ h_this->SetField32Volatile<true>(OFFSET_OF_OBJECT_MEMBER(Class, status_), new_status);
} else {
- SetField32Volatile<false>(OFFSET_OF_OBJECT_MEMBER(Class, status_), new_status);
+ h_this->SetField32Volatile<false>(OFFSET_OF_OBJECT_MEMBER(Class, status_), new_status);
}
if (!class_linker_initialized) {
@@ -121,17 +122,17 @@ void Class::SetStatus(Status new_status, Thread* self) {
} else {
// Classes that are being resolved or initialized need to notify waiters that the class status
// changed. See ClassLinker::EnsureResolved and ClassLinker::WaitForInitializeClass.
- if (IsTemp()) {
+ if (h_this->IsTemp()) {
// Class is a temporary one, ensure that waiters for resolution get notified of retirement
// so that they can grab the new version of the class from the class linker's table.
- CHECK_LT(new_status, kStatusResolved) << PrettyDescriptor(this);
+ CHECK_LT(new_status, kStatusResolved) << PrettyDescriptor(h_this.Get());
if (new_status == kStatusRetired || new_status == kStatusError) {
- NotifyAll(self);
+ h_this->NotifyAll(self);
}
} else {
CHECK_NE(new_status, kStatusRetired);
if (old_status >= kStatusResolved || new_status >= kStatusResolved) {
- NotifyAll(self);
+ h_this->NotifyAll(self);
}
}
}
@@ -828,11 +829,12 @@ class CopyClassVisitor {
void operator()(Object* obj, size_t usable_size) const
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
UNUSED(usable_size);
- mirror::Class* new_class_obj = obj->AsClass();
- mirror::Object::CopyObject(self_, new_class_obj, orig_->Get(), copy_bytes_);
- new_class_obj->SetStatus(Class::kStatusResolving, self_);
- new_class_obj->PopulateEmbeddedImtAndVTable(imt_handle_scope_);
- new_class_obj->SetClassSize(new_length_);
+ StackHandleScope<1> hs(self_);
+ Handle<mirror::Class> h_new_class_obj(hs.NewHandle(obj->AsClass()));
+ mirror::Object::CopyObject(self_, h_new_class_obj.Get(), orig_->Get(), copy_bytes_);
+ mirror::Class::SetStatus(h_new_class_obj, Class::kStatusResolving, self_);
+ h_new_class_obj->PopulateEmbeddedImtAndVTable(imt_handle_scope_);
+ h_new_class_obj->SetClassSize(new_length_);
}
private:
diff --git a/runtime/mirror/class.h b/runtime/mirror/class.h
index bd49754731..e7f7c6e96c 100644
--- a/runtime/mirror/class.h
+++ b/runtime/mirror/class.h
@@ -140,7 +140,9 @@ class MANAGED Class FINAL : public Object {
GetField32Volatile<kVerifyFlags>(OFFSET_OF_OBJECT_MEMBER(Class, status_)));
}
- void SetStatus(Status new_status, Thread* self) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ // This is static because 'this' may be moved by GC.
+ static void SetStatus(Handle<Class> h_this, Status new_status, Thread* self)
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
static MemberOffset StatusOffset() {
return OFFSET_OF_OBJECT_MEMBER(Class, status_);