Move Transaction logs to arena allocator.

And change some containers to reduce memory usage.

Also update `SafeMap` with some C++17 functions, namely all
`erase()` and `extract()` overloads and `insert()` overloads
taking a "node". The `extract()` and `insert()` overloads
are convenient to avoid allocation/dealocation when updating
the key of an entry.

Test: m test-art-host-gtest
Test: testrunner.py --host --optimizing
Bug: 181943478
Change-Id: I791d00598ac288b1f31c92daa63b5b3dcf6b41fa
diff --git a/runtime/runtime.cc b/runtime/runtime.cc
index 7a9c7fa..5a49f50 100644
--- a/runtime/runtime.cc
+++ b/runtime/runtime.cc
@@ -2416,8 +2416,8 @@
 }
 
 void Runtime::VisitTransactionRoots(RootVisitor* visitor) {
-  for (auto& transaction : preinitialization_transactions_) {
-    transaction->VisitRoots(visitor);
+  for (Transaction& transaction : preinitialization_transactions_) {
+    transaction.VisitRoots(visitor);
   }
 }
 
@@ -2668,26 +2668,33 @@
 
 void Runtime::EnterTransactionMode(bool strict, mirror::Class* root) {
   DCHECK(IsAotCompiler());
+  ArenaPool* arena_pool = nullptr;
+  ArenaStack* arena_stack = nullptr;
   if (preinitialization_transactions_.empty()) {  // Top-level transaction?
     // Make initialized classes visibly initialized now. If that happened during the transaction
     // and then the transaction was aborted, we would roll back the status update but not the
     // ClassLinker's bookkeeping structures, so these classes would never be visibly initialized.
     GetClassLinker()->MakeInitializedClassesVisiblyInitialized(Thread::Current(), /*wait=*/ true);
+    // Pass the runtime `ArenaPool` to the transaction.
+    arena_pool = GetArenaPool();
+  } else {
+    // Pass the `ArenaStack` from previous transaction to the new one.
+    arena_stack = preinitialization_transactions_.front().GetArenaStack();
   }
-  preinitialization_transactions_.push_back(std::make_unique<Transaction>(strict, root));
+  preinitialization_transactions_.emplace_front(strict, root, arena_stack, arena_pool);
 }
 
 void Runtime::ExitTransactionMode() {
   DCHECK(IsAotCompiler());
   DCHECK(IsActiveTransaction());
-  preinitialization_transactions_.pop_back();
+  preinitialization_transactions_.pop_front();
 }
 
 void Runtime::RollbackAndExitTransactionMode() {
   DCHECK(IsAotCompiler());
   DCHECK(IsActiveTransaction());
-  preinitialization_transactions_.back()->Rollback();
-  preinitialization_transactions_.pop_back();
+  preinitialization_transactions_.front().Rollback();
+  preinitialization_transactions_.pop_front();
 }
 
 bool Runtime::IsTransactionAborted() const {
@@ -2711,9 +2718,14 @@
   return IsActiveTransaction() && GetTransaction()->IsStrict();
 }
 
-const std::unique_ptr<Transaction>& Runtime::GetTransaction() const {
+const Transaction* Runtime::GetTransaction() const {
   DCHECK(!preinitialization_transactions_.empty());
-  return preinitialization_transactions_.back();
+  return &preinitialization_transactions_.front();
+}
+
+Transaction* Runtime::GetTransaction() {
+  DCHECK(!preinitialization_transactions_.empty());
+  return &preinitialization_transactions_.front();
 }
 
 void Runtime::AbortTransactionAndThrowAbortError(Thread* self, const std::string& abort_message) {
@@ -2735,43 +2747,55 @@
   GetTransaction()->ThrowAbortError(self, nullptr);
 }
 
-void Runtime::RecordWriteFieldBoolean(mirror::Object* obj, MemberOffset field_offset,
-                                      uint8_t value, bool is_volatile) const {
+void Runtime::RecordWriteFieldBoolean(mirror::Object* obj,
+                                      MemberOffset field_offset,
+                                      uint8_t value,
+                                      bool is_volatile) {
   DCHECK(IsAotCompiler());
   DCHECK(IsActiveTransaction());
   GetTransaction()->RecordWriteFieldBoolean(obj, field_offset, value, is_volatile);
 }
 
-void Runtime::RecordWriteFieldByte(mirror::Object* obj, MemberOffset field_offset,
-                                   int8_t value, bool is_volatile) const {
+void Runtime::RecordWriteFieldByte(mirror::Object* obj,
+                                   MemberOffset field_offset,
+                                   int8_t value,
+                                   bool is_volatile) {
   DCHECK(IsAotCompiler());
   DCHECK(IsActiveTransaction());
   GetTransaction()->RecordWriteFieldByte(obj, field_offset, value, is_volatile);
 }
 
-void Runtime::RecordWriteFieldChar(mirror::Object* obj, MemberOffset field_offset,
-                                   uint16_t value, bool is_volatile) const {
+void Runtime::RecordWriteFieldChar(mirror::Object* obj,
+                                   MemberOffset field_offset,
+                                   uint16_t value,
+                                   bool is_volatile) {
   DCHECK(IsAotCompiler());
   DCHECK(IsActiveTransaction());
   GetTransaction()->RecordWriteFieldChar(obj, field_offset, value, is_volatile);
 }
 
-void Runtime::RecordWriteFieldShort(mirror::Object* obj, MemberOffset field_offset,
-                                    int16_t value, bool is_volatile) const {
+void Runtime::RecordWriteFieldShort(mirror::Object* obj,
+                                    MemberOffset field_offset,
+                                    int16_t value,
+                                    bool is_volatile) {
   DCHECK(IsAotCompiler());
   DCHECK(IsActiveTransaction());
   GetTransaction()->RecordWriteFieldShort(obj, field_offset, value, is_volatile);
 }
 
-void Runtime::RecordWriteField32(mirror::Object* obj, MemberOffset field_offset,
-                                 uint32_t value, bool is_volatile) const {
+void Runtime::RecordWriteField32(mirror::Object* obj,
+                                 MemberOffset field_offset,
+                                 uint32_t value,
+                                 bool is_volatile) {
   DCHECK(IsAotCompiler());
   DCHECK(IsActiveTransaction());
   GetTransaction()->RecordWriteField32(obj, field_offset, value, is_volatile);
 }
 
-void Runtime::RecordWriteField64(mirror::Object* obj, MemberOffset field_offset,
-                                 uint64_t value, bool is_volatile) const {
+void Runtime::RecordWriteField64(mirror::Object* obj,
+                                 MemberOffset field_offset,
+                                 uint64_t value,
+                                 bool is_volatile) {
   DCHECK(IsAotCompiler());
   DCHECK(IsActiveTransaction());
   GetTransaction()->RecordWriteField64(obj, field_offset, value, is_volatile);
@@ -2780,54 +2804,51 @@
 void Runtime::RecordWriteFieldReference(mirror::Object* obj,
                                         MemberOffset field_offset,
                                         ObjPtr<mirror::Object> value,
-                                        bool is_volatile) const {
+                                        bool is_volatile) {
   DCHECK(IsAotCompiler());
   DCHECK(IsActiveTransaction());
-  GetTransaction()->RecordWriteFieldReference(obj,
-                                                            field_offset,
-                                                            value.Ptr(),
-                                                            is_volatile);
+  GetTransaction()->RecordWriteFieldReference(obj, field_offset, value.Ptr(), is_volatile);
 }
 
-void Runtime::RecordWriteArray(mirror::Array* array, size_t index, uint64_t value) const {
+void Runtime::RecordWriteArray(mirror::Array* array, size_t index, uint64_t value) {
   DCHECK(IsAotCompiler());
   DCHECK(IsActiveTransaction());
   GetTransaction()->RecordWriteArray(array, index, value);
 }
 
-void Runtime::RecordStrongStringInsertion(ObjPtr<mirror::String> s) const {
+void Runtime::RecordStrongStringInsertion(ObjPtr<mirror::String> s) {
   DCHECK(IsAotCompiler());
   DCHECK(IsActiveTransaction());
   GetTransaction()->RecordStrongStringInsertion(s);
 }
 
-void Runtime::RecordWeakStringInsertion(ObjPtr<mirror::String> s) const {
+void Runtime::RecordWeakStringInsertion(ObjPtr<mirror::String> s) {
   DCHECK(IsAotCompiler());
   DCHECK(IsActiveTransaction());
   GetTransaction()->RecordWeakStringInsertion(s);
 }
 
-void Runtime::RecordStrongStringRemoval(ObjPtr<mirror::String> s) const {
+void Runtime::RecordStrongStringRemoval(ObjPtr<mirror::String> s) {
   DCHECK(IsAotCompiler());
   DCHECK(IsActiveTransaction());
   GetTransaction()->RecordStrongStringRemoval(s);
 }
 
-void Runtime::RecordWeakStringRemoval(ObjPtr<mirror::String> s) const {
+void Runtime::RecordWeakStringRemoval(ObjPtr<mirror::String> s) {
   DCHECK(IsAotCompiler());
   DCHECK(IsActiveTransaction());
   GetTransaction()->RecordWeakStringRemoval(s);
 }
 
 void Runtime::RecordResolveString(ObjPtr<mirror::DexCache> dex_cache,
-                                  dex::StringIndex string_idx) const {
+                                  dex::StringIndex string_idx) {
   DCHECK(IsAotCompiler());
   DCHECK(IsActiveTransaction());
   GetTransaction()->RecordResolveString(dex_cache, string_idx);
 }
 
 void Runtime::RecordResolveMethodType(ObjPtr<mirror::DexCache> dex_cache,
-                                      dex::ProtoIndex proto_idx) const {
+                                      dex::ProtoIndex proto_idx) {
   DCHECK(IsAotCompiler());
   DCHECK(IsActiveTransaction());
   GetTransaction()->RecordResolveMethodType(dex_cache, proto_idx);