Follow-up 128393
Avoids false warning when initializing the exception's class by
marking the transaction aborted after throwing the InternalError
exception.
Also uses VLOG(compiler) to print the warning since it's only useful
when investigating ahead-of-time class initialization.
Bug: 19202032
Change-Id: I3c53639cbb888086ad345d668d1e5b73c5aaf861
diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc
index ee5eefb..af6f7a9 100644
--- a/runtime/class_linker.cc
+++ b/runtime/class_linker.cc
@@ -4240,8 +4240,8 @@
} else if (Runtime::Current()->IsTransactionAborted()) {
// The exception thrown when the transaction aborted has been caught and cleared
// so we need to throw it again now.
- LOG(WARNING) << "Return from class initializer of " << PrettyDescriptor(klass.Get())
- << " without exception while transaction was aborted: re-throw it now.";
+ VLOG(compiler) << "Return from class initializer of " << PrettyDescriptor(klass.Get())
+ << " without exception while transaction was aborted: re-throw it now.";
Runtime::Current()->ThrowInternalErrorForAbortedTransaction(self);
klass->SetStatus(mirror::Class::kStatusError, self);
success = false;
diff --git a/runtime/runtime.cc b/runtime/runtime.cc
index 8c5827c..824d65f 100644
--- a/runtime/runtime.cc
+++ b/runtime/runtime.cc
@@ -1560,15 +1560,17 @@
const std::string& abort_message) {
DCHECK(IsCompiler());
DCHECK(IsActiveTransaction());
+ // Throwing an exception may cause its class initialization. If we mark the transaction
+ // aborted before that, we may warn with a false alarm. Throwing the exception before
+ // marking the transaction aborted avoids that.
+ preinitialization_transaction_->ThrowInternalError(self, false);
preinitialization_transaction_->Abort(abort_message);
- ThrowInternalErrorForAbortedTransaction(self);
}
void Runtime::ThrowInternalErrorForAbortedTransaction(Thread* self) {
DCHECK(IsCompiler());
DCHECK(IsActiveTransaction());
- DCHECK(IsTransactionAborted());
- preinitialization_transaction_->ThrowInternalError(self);
+ preinitialization_transaction_->ThrowInternalError(self, true);
}
void Runtime::RecordWriteFieldBoolean(mirror::Object* obj, MemberOffset field_offset,
diff --git a/runtime/transaction.cc b/runtime/transaction.cc
index e26f955..c0fd7a5 100644
--- a/runtime/transaction.cc
+++ b/runtime/transaction.cc
@@ -70,8 +70,10 @@
}
}
-void Transaction::ThrowInternalError(Thread* self) {
- DCHECK(IsAborted());
+void Transaction::ThrowInternalError(Thread* self, bool rethrow) {
+ if (kIsDebugBuild && rethrow) {
+ CHECK(IsAborted()) << "Rethrow InternalError while transaction is not aborted";
+ }
std::string abort_msg(GetAbortMessage());
self->ThrowNewException(self->GetCurrentLocationForThrow(), "Ljava/lang/InternalError;",
abort_msg.c_str());
diff --git a/runtime/transaction.h b/runtime/transaction.h
index be614f9..e1b93c9 100644
--- a/runtime/transaction.h
+++ b/runtime/transaction.h
@@ -45,7 +45,7 @@
void Abort(const std::string& abort_message)
LOCKS_EXCLUDED(log_lock_)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- void ThrowInternalError(Thread* self)
+ void ThrowInternalError(Thread* self, bool rethrow)
LOCKS_EXCLUDED(log_lock_)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
bool IsAborted() LOCKS_EXCLUDED(log_lock_);