Track class initializing in transaction

Add a field and a corresponding constructor to transaction which keeps
track of the class that the transaction is initializing.

To implement constraints for <clinit> behaviors, the transaction needs
to know which class it is initializing.

Test: make test-art-host -j64
Change-Id: I87b3fcb3ef15914c79c6687ec8a87058265eaead
diff --git a/compiler/driver/compiler_driver.cc b/compiler/driver/compiler_driver.cc
index 7970b4c..dd58bc7 100644
--- a/compiler/driver/compiler_driver.cc
+++ b/compiler/driver/compiler_driver.cc
@@ -2332,7 +2332,7 @@
             // checks in Thread::AssertThreadSuspensionIsAllowable.
             Runtime* const runtime = Runtime::Current();
             // Run the class initializer in transaction mode.
-            runtime->EnterTransactionMode();
+            runtime->EnterTransactionMode(klass.Get());
             bool success = manager_->GetClassLinker()->EnsureInitialized(soa.Self(), klass, true,
                                                                          true);
             // TODO we detach transaction from runtime to indicate we quit the transactional
diff --git a/runtime/runtime.cc b/runtime/runtime.cc
index 01b87b9..2366e10 100644
--- a/runtime/runtime.cc
+++ b/runtime/runtime.cc
@@ -2071,6 +2071,11 @@
   preinitialization_transaction_ = std::make_unique<Transaction>();
 }
 
+void Runtime::EnterTransactionMode(mirror::Class* root) {
+  DCHECK(IsAotCompiler());
+  preinitialization_transaction_ = std::make_unique<Transaction>(root);
+}
+
 void Runtime::ExitTransactionMode() {
   DCHECK(IsAotCompiler());
   preinitialization_transaction_ = nullptr;
diff --git a/runtime/runtime.h b/runtime/runtime.h
index 0200dc0..9424596 100644
--- a/runtime/runtime.h
+++ b/runtime/runtime.h
@@ -459,6 +459,7 @@
     return preinitialization_transaction_ != nullptr;
   }
   void EnterTransactionMode();
+  void EnterTransactionMode(mirror::Class* root);
   void ExitTransactionMode();
   // Transaction rollback and exit transaction are always done together, it's convenience to
   // do them in one function.
diff --git a/runtime/transaction.cc b/runtime/transaction.cc
index 907d37e..359030e 100644
--- a/runtime/transaction.cc
+++ b/runtime/transaction.cc
@@ -38,6 +38,10 @@
   CHECK(Runtime::Current()->IsAotCompiler());
 }
 
+Transaction::Transaction(mirror::Class* root) : Transaction() {
+  root_ = root;
+}
+
 Transaction::~Transaction() {
   if (kEnableTransactionStats) {
     MutexLock mu(Thread::Current(), log_lock_);
@@ -270,6 +274,7 @@
 
 void Transaction::VisitRoots(RootVisitor* visitor) {
   MutexLock mu(Thread::Current(), log_lock_);
+  visitor->VisitRoot(reinterpret_cast<mirror::Object**>(&root_), RootInfo(kRootUnknown));
   VisitObjectLogs(visitor);
   VisitArrayLogs(visitor);
   VisitInternStringLogs(visitor);
diff --git a/runtime/transaction.h b/runtime/transaction.h
index 747c2d0..22518f6 100644
--- a/runtime/transaction.h
+++ b/runtime/transaction.h
@@ -32,6 +32,7 @@
 namespace art {
 namespace mirror {
 class Array;
+class Class;
 class DexCache;
 class Object;
 class String;
@@ -44,6 +45,7 @@
   static constexpr const char* kAbortExceptionSignature = "Ldalvik/system/TransactionAbortError;";
 
   Transaction();
+  explicit Transaction(mirror::Class* root);
   ~Transaction();
 
   void Abort(const std::string& abort_message)
@@ -288,6 +290,7 @@
   std::list<ResolveStringLog> resolve_string_logs_ GUARDED_BY(log_lock_);
   bool aborted_ GUARDED_BY(log_lock_);
   std::string abort_message_ GUARDED_BY(log_lock_);
+  mirror::Class* root_ GUARDED_BY(log_lock_);
 
   DISALLOW_COPY_AND_ASSIGN(Transaction);
 };