transaction.cc revision a559ccb7aa56a5871b1e77857c2b5e7101b8d371
1d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz/*
2d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz * Copyright (C) 2014 The Android Open Source Project
3d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz *
4d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz * Licensed under the Apache License, Version 2.0 (the "License");
5d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz * you may not use this file except in compliance with the License.
6d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz * You may obtain a copy of the License at
7d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz *
8d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz *      http://www.apache.org/licenses/LICENSE-2.0
9d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz *
10d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz * Unless required by applicable law or agreed to in writing, software
11d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz * distributed under the License is distributed on an "AS IS" BASIS,
12d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz * See the License for the specific language governing permissions and
14d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz * limitations under the License.
15d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz */
16d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz
17d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz#include "transaction.h"
18d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz
19d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz#include "base/stl_util.h"
20d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz#include "base/logging.h"
21d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz#include "gc/accounting/card_table-inl.h"
22d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz#include "intern_table.h"
23d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz#include "mirror/object-inl.h"
24d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz#include "mirror/object_array-inl.h"
25d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz
26d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz#include <list>
27d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz
28d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertznamespace art {
29d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz
30d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz// TODO: remove (only used for debugging purpose).
31d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertzstatic constexpr bool kEnableTransactionStats = false;
32d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz
33d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien HertzTransaction::Transaction() : log_lock_("transaction log lock", kTransactionLogLock) {
34d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz  CHECK(Runtime::Current()->IsCompiler());
35d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz}
36d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz
37d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien HertzTransaction::~Transaction() {
38d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz  if (kEnableTransactionStats) {
39d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz    MutexLock mu(Thread::Current(), log_lock_);
40d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz    size_t objects_count = object_logs_.size();
41d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz    size_t field_values_count = 0;
42d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz    for (auto it : object_logs_) {
43d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz      field_values_count += it.second.Size();
44d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz    }
45d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz    size_t array_count = array_logs_.size();
46d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz    size_t array_values_count = 0;
47d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz    for (auto it : array_logs_) {
48d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz      array_values_count += it.second.Size();
49d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz    }
50d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz    size_t string_count = intern_string_logs_.size();
51d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz    LOG(INFO) << "Transaction::~Transaction"
52d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz              << ": objects_count=" << objects_count
53d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz              << ", field_values_count=" << field_values_count
54d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz              << ", array_count=" << array_count
55d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz              << ", array_values_count=" << array_values_count
56d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz              << ", string_count=" << string_count;
57d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz  }
58d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz}
59d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz
60d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertzvoid Transaction::RecordWriteField32(mirror::Object* obj, MemberOffset field_offset, uint32_t value,
61d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz                                     bool is_volatile) {
62d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz  DCHECK(obj != nullptr);
63d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz  MutexLock mu(Thread::Current(), log_lock_);
64d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz  ObjectLog& object_log = object_logs_[obj];
65d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz  object_log.Log32BitsValue(field_offset, value, is_volatile);
66d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz}
67d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz
68d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertzvoid Transaction::RecordWriteField64(mirror::Object* obj, MemberOffset field_offset, uint64_t value,
69d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz                                     bool is_volatile) {
70d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz  DCHECK(obj != nullptr);
71d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz  MutexLock mu(Thread::Current(), log_lock_);
72d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz  ObjectLog& object_log = object_logs_[obj];
73d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz  object_log.Log64BitsValue(field_offset, value, is_volatile);
74d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz}
75d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz
76d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertzvoid Transaction::RecordWriteFieldReference(mirror::Object* obj, MemberOffset field_offset,
77d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz                                            mirror::Object* value, bool is_volatile) {
78d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz  DCHECK(obj != nullptr);
79d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz  MutexLock mu(Thread::Current(), log_lock_);
80d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz  ObjectLog& object_log = object_logs_[obj];
81d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz  object_log.LogReferenceValue(field_offset, value, is_volatile);
82d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz}
83d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz
84d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertzvoid Transaction::RecordWriteArray(mirror::Array* array, size_t index, uint64_t value) {
85d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz  DCHECK(array != nullptr);
86d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz  DCHECK(array->IsArrayInstance());
87d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz  MutexLock mu(Thread::Current(), log_lock_);
88d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz  ArrayLog& array_log = array_logs_[array];
89d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz  array_log.LogValue(index, value);
90d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz}
91d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz
92d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertzvoid Transaction::RecordStrongStringInsertion(mirror::String* s, uint32_t hash_code) {
93d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz  DCHECK(s != nullptr);
94d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz  InternStringLog log(s, hash_code, InternStringLog::kStrongString, InternStringLog::kInsert);
95d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz  LogInternedString(log);
96d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz}
97d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz
98d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertzvoid Transaction::RecordWeakStringInsertion(mirror::String* s, uint32_t hash_code) {
99d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz  DCHECK(s != nullptr);
100d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz  InternStringLog log(s, hash_code, InternStringLog::kWeakString, InternStringLog::kInsert);
101d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz  LogInternedString(log);
102d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz}
103d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz
104d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertzvoid Transaction::RecordStrongStringRemoval(mirror::String* s, uint32_t hash_code) {
105d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz  InternStringLog log(s, hash_code, InternStringLog::kStrongString, InternStringLog::kRemove);
106d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz  LogInternedString(log);
107d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz}
108d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz
109d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertzvoid Transaction::RecordWeakStringRemoval(mirror::String* s, uint32_t hash_code) {
110d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz  InternStringLog log(s, hash_code, InternStringLog::kWeakString, InternStringLog::kRemove);
111d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz  LogInternedString(log);
112d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz}
113d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz
114d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertzvoid Transaction::LogInternedString(InternStringLog& log) {
115d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz  Locks::intern_table_lock_->AssertExclusiveHeld(Thread::Current());
116d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz  MutexLock mu(Thread::Current(), log_lock_);
117d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz  intern_string_logs_.push_front(log);
118d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz}
119d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz
120d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertzvoid Transaction::Abort() {
121d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz  CHECK(!Runtime::Current()->IsActiveTransaction());
122d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz  Thread* self = Thread::Current();
123d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz  self->AssertNoPendingException();
124d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz  MutexLock mu1(self, *Locks::intern_table_lock_);
125d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz  MutexLock mu2(self, log_lock_);
126d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz  UndoObjectModifications();
127d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz  UndoArrayModifications();
128d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz  UndoInternStringTableModifications();
129d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz}
130d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz
131d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertzvoid Transaction::UndoObjectModifications() {
132d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz  // TODO we may not need to restore objects allocated during this transaction. Or we could directly
133d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz  // remove them from the heap.
134d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz  for (auto it : object_logs_) {
135d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz    it.second.Undo(it.first);
136d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz  }
137d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz  object_logs_.clear();
138d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz}
139d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz
140d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertzvoid Transaction::UndoArrayModifications() {
141d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz  // TODO we may not need to restore array allocated during this transaction. Or we could directly
142d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz  // remove them from the heap.
143d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz  for (auto it : array_logs_) {
144d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz    it.second.Undo(it.first);
145d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz  }
146d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz  array_logs_.clear();
147d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz}
148d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz
149d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertzvoid Transaction::UndoInternStringTableModifications() {
150d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz  InternTable* const intern_table = Runtime::Current()->GetInternTable();
151d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz  // We want to undo each operation from the most recent to the oldest. List has been filled so the
152d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz  // most recent operation is at list begin so just have to iterate over it.
153d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz  for (InternStringLog& string_log : intern_string_logs_) {
154d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz    string_log.Undo(intern_table);
155d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz  }
156d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz  intern_string_logs_.clear();
157d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz}
158d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz
159d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertzvoid Transaction::VisitRoots(RootCallback* callback, void* arg) {
160d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz  MutexLock mu(Thread::Current(), log_lock_);
161d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz  VisitObjectLogs(callback, arg);
162d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz  VisitArrayLogs(callback, arg);
163d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz  VisitStringLogs(callback, arg);
164d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz}
165d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz
166d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertzvoid Transaction::VisitObjectLogs(RootCallback* callback, void* arg) {
167d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz  // List of moving roots.
168d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz  typedef std::pair<mirror::Object*, mirror::Object*> ObjectPair;
169d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz  std::list<ObjectPair> moving_roots;
170d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz
171d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz  // Visit roots.
172d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz  for (auto it : object_logs_) {
173d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz    it.second.VisitRoots(callback, arg);
174d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz    mirror::Object* old_root = it.first;
175815873ecc312b1d231acce71e1a16f42cdaf09f2Mathieu Chartier    mirror::Object* new_root = old_root;
176815873ecc312b1d231acce71e1a16f42cdaf09f2Mathieu Chartier    callback(&new_root, arg, 0, kRootUnknown);
177d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz    if (new_root != old_root) {
178d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz      moving_roots.push_back(std::make_pair(old_root, new_root));
179d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz    }
180d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz  }
181d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz
182d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz  // Update object logs with moving roots.
183d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz  for (const ObjectPair& pair : moving_roots) {
184d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz    mirror::Object* old_root = pair.first;
185d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz    mirror::Object* new_root = pair.second;
186d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz    auto old_root_it = object_logs_.find(old_root);
187d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz    CHECK(old_root_it != object_logs_.end());
188d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz    CHECK(object_logs_.find(new_root) == object_logs_.end());
189d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz    object_logs_.insert(std::make_pair(new_root, old_root_it->second));
190d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz    object_logs_.erase(old_root_it);
191d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz  }
192d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz}
193d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz
194d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertzvoid Transaction::VisitArrayLogs(RootCallback* callback, void* arg) {
195d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz  // List of moving roots.
196d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz  typedef std::pair<mirror::Array*, mirror::Array*> ArrayPair;
197d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz  std::list<ArrayPair> moving_roots;
198d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz
199d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz  for (auto it : array_logs_) {
200d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz    mirror::Array* old_root = it.first;
201d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz    if (old_root->IsObjectArray()) {
202d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz      it.second.VisitRoots(callback, arg);
203d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz    }
204815873ecc312b1d231acce71e1a16f42cdaf09f2Mathieu Chartier    mirror::Array* new_root = old_root;
205815873ecc312b1d231acce71e1a16f42cdaf09f2Mathieu Chartier    callback(reinterpret_cast<mirror::Object**>(&new_root), arg, 0, kRootUnknown);
206d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz    if (new_root != old_root) {
207d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz      moving_roots.push_back(std::make_pair(old_root, new_root));
208d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz    }
209d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz  }
210d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz
211d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz  // Update array logs with moving roots.
212d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz  for (const ArrayPair& pair : moving_roots) {
213d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz    mirror::Array* old_root = pair.first;
214d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz    mirror::Array* new_root = pair.second;
215d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz    auto old_root_it = array_logs_.find(old_root);
216d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz    CHECK(old_root_it != array_logs_.end());
217d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz    CHECK(array_logs_.find(new_root) == array_logs_.end());
218d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz    array_logs_.insert(std::make_pair(new_root, old_root_it->second));
219d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz    array_logs_.erase(old_root_it);
220d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz  }
221d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz}
222d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz
223d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertzvoid Transaction::VisitStringLogs(RootCallback* callback, void* arg) {
224d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz  for (InternStringLog& log : intern_string_logs_) {
225d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz    log.VisitRoots(callback, arg);
226d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz  }
227d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz}
228d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz
229d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertzvoid Transaction::ObjectLog::Log32BitsValue(MemberOffset offset, uint32_t value, bool is_volatile) {
230d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz  auto it = field_values_.find(offset.Uint32Value());
231d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz  if (it == field_values_.end()) {
232d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz    ObjectLog::FieldValue field_value;
233d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz    field_value.value = value;
234d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz    field_value.is_volatile = is_volatile;
235d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz    field_value.kind = ObjectLog::k32Bits;
236d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz    field_values_.insert(std::make_pair(offset.Uint32Value(), field_value));
237d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz  }
238d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz}
239d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz
240d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertzvoid Transaction::ObjectLog::Log64BitsValue(MemberOffset offset, uint64_t value, bool is_volatile) {
241d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz  auto it = field_values_.find(offset.Uint32Value());
242d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz  if (it == field_values_.end()) {
243d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz    ObjectLog::FieldValue field_value;
244d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz    field_value.value = value;
245d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz    field_value.is_volatile = is_volatile;
246d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz    field_value.kind = ObjectLog::k64Bits;
247d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz    field_values_.insert(std::make_pair(offset.Uint32Value(), field_value));
248d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz  }
249d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz}
250d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz
251d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertzvoid Transaction::ObjectLog::LogReferenceValue(MemberOffset offset, mirror::Object* obj, bool is_volatile) {
252d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz  auto it = field_values_.find(offset.Uint32Value());
253d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz  if (it == field_values_.end()) {
254d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz    ObjectLog::FieldValue field_value;
255d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz    field_value.value = reinterpret_cast<uintptr_t>(obj);
256d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz    field_value.is_volatile = is_volatile;
257d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz    field_value.kind = ObjectLog::kReference;
258d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz    field_values_.insert(std::make_pair(offset.Uint32Value(), field_value));
259d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz  }
260d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz}
261d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz
262d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertzvoid Transaction::ObjectLog::Undo(mirror::Object* obj) {
263d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz  for (auto& it : field_values_) {
264d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz    // Garbage collector needs to access object's class and array's length. So we don't rollback
265d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz    // these values.
266d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz    MemberOffset field_offset(it.first);
267d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz    if (field_offset.Uint32Value() == mirror::Class::ClassOffset().Uint32Value()) {
268d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz      // Skip Object::class field.
269d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz      continue;
270d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz    }
271d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz    if (obj->IsArrayInstance() &&
272d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz        field_offset.Uint32Value() == mirror::Array::LengthOffset().Uint32Value()) {
273d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz      // Skip Array::length field.
274d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz      continue;
275d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz    }
276d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz    FieldValue& field_value = it.second;
277d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz    UndoFieldWrite(obj, field_offset, field_value);
278d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz  }
279d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz}
280d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz
281d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertzvoid Transaction::ObjectLog::UndoFieldWrite(mirror::Object* obj, MemberOffset field_offset,
282d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz                                            const FieldValue& field_value) {
283d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz  // TODO We may want to abort a transaction while still being in transaction mode. In this case,
284d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz  // we'd need to disable the check.
285d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz  constexpr bool kCheckTransaction = true;
286d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz  switch (field_value.kind) {
287d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz    case k32Bits:
288d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz      obj->SetField32<false, kCheckTransaction>(field_offset, static_cast<uint32_t>(field_value.value),
289d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz                                                field_value.is_volatile);
290d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz      break;
291d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz    case k64Bits:
292d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz      obj->SetField64<false, kCheckTransaction>(field_offset, field_value.value,
293d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz                                                field_value.is_volatile);
294d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz      break;
295d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz    case kReference:
296d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz      obj->SetFieldObject<false, kCheckTransaction>(field_offset,
297d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz                                                    reinterpret_cast<mirror::Object*>(field_value.value),
298d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz                                                    field_value.is_volatile);
299d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz      break;
300d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz    default:
301d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz      LOG(FATAL) << "Unknown value kind " << field_value.kind;
302d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz      break;
303d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz  }
304d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz}
305d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz
306d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertzvoid Transaction::ObjectLog::VisitRoots(RootCallback* callback, void* arg) {
307d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz  for (auto it : field_values_) {
308d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz    FieldValue& field_value = it.second;
309d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz    if (field_value.kind == ObjectLog::kReference) {
310815873ecc312b1d231acce71e1a16f42cdaf09f2Mathieu Chartier      mirror::Object* obj =
311815873ecc312b1d231acce71e1a16f42cdaf09f2Mathieu Chartier          reinterpret_cast<mirror::Object*>(static_cast<uintptr_t>(field_value.value));
312a559ccb7aa56a5871b1e77857c2b5e7101b8d371Sebastien Hertz      if (obj != nullptr) {
313a559ccb7aa56a5871b1e77857c2b5e7101b8d371Sebastien Hertz        callback(&obj, arg, 0, kRootUnknown);
314a559ccb7aa56a5871b1e77857c2b5e7101b8d371Sebastien Hertz        field_value.value = reinterpret_cast<uintptr_t>(obj);
315a559ccb7aa56a5871b1e77857c2b5e7101b8d371Sebastien Hertz      }
316d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz    }
317d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz  }
318d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz}
319d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz
320d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertzvoid Transaction::InternStringLog::Undo(InternTable* intern_table) {
321d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz  DCHECK(intern_table != nullptr);
322d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz  switch (string_op_) {
323d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz      case InternStringLog::kInsert: {
324d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz        switch (string_kind_) {
325d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz          case InternStringLog::kStrongString:
326d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz            intern_table->RemoveStrongFromTransaction(str_, hash_code_);
327d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz            break;
328d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz          case InternStringLog::kWeakString:
329d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz            intern_table->RemoveWeakFromTransaction(str_, hash_code_);
330d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz            break;
331d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz          default:
332d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz            LOG(FATAL) << "Unknown interned string kind";
333d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz            break;
334d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz        }
335d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz        break;
336d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz      }
337d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz      case InternStringLog::kRemove: {
338d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz        switch (string_kind_) {
339d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz          case InternStringLog::kStrongString:
340d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz            intern_table->InsertStrongFromTransaction(str_, hash_code_);
341d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz            break;
342d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz          case InternStringLog::kWeakString:
343d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz            intern_table->InsertWeakFromTransaction(str_, hash_code_);
344d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz            break;
345d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz          default:
346d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz            LOG(FATAL) << "Unknown interned string kind";
347d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz            break;
348d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz        }
349d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz        break;
350d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz      }
351d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz      default:
352d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz        LOG(FATAL) << "Unknown interned string op";
353d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz        break;
354d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz    }
355d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz}
356d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz
357d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertzvoid Transaction::InternStringLog::VisitRoots(RootCallback* callback, void* arg) {
358815873ecc312b1d231acce71e1a16f42cdaf09f2Mathieu Chartier  callback(reinterpret_cast<mirror::Object**>(&str_), arg, 0, kRootInternedString);
359d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz}
360d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz
361d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertzvoid Transaction::ArrayLog::LogValue(size_t index, uint64_t value) {
362d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz  auto it = array_values_.find(index);
363d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz  if (it == array_values_.end()) {
364d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz    array_values_.insert(std::make_pair(index, value));
365d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz  }
366d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz}
367d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz
368d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertzvoid Transaction::ArrayLog::Undo(mirror::Array* array) {
369d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz  DCHECK(array != nullptr);
370d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz  DCHECK(array->IsArrayInstance());
371d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz  Primitive::Type type = array->GetClass()->GetComponentType()->GetPrimitiveType();
372d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz  for (auto it : array_values_) {
373d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz    UndoArrayWrite(array, type, it.first, it.second);
374d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz  }
375d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz}
376d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz
377d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertzvoid Transaction::ArrayLog::UndoArrayWrite(mirror::Array* array, Primitive::Type array_type,
378d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz                                           size_t index, uint64_t value) {
379d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz  // TODO We may want to abort a transaction while still being in transaction mode. In this case,
380d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz  // we'd need to disable the check.
381d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz  switch (array_type) {
382d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz    case Primitive::kPrimBoolean:
383d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz      array->AsBooleanArray()->SetWithoutChecks<false>(index, static_cast<uint8_t>(value));
384d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz      break;
385d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz    case Primitive::kPrimByte:
386d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz      array->AsByteArray()->SetWithoutChecks<false>(index, static_cast<int8_t>(value));
387d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz      break;
388d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz    case Primitive::kPrimChar:
389d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz      array->AsCharArray()->SetWithoutChecks<false>(index, static_cast<uint16_t>(value));
390d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz      break;
391d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz    case Primitive::kPrimShort:
392d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz      array->AsShortArray()->SetWithoutChecks<false>(index, static_cast<int16_t>(value));
393d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz      break;
394d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz    case Primitive::kPrimInt:
395d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz      array->AsIntArray()->SetWithoutChecks<false>(index, static_cast<int32_t>(value));
396d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz      break;
397d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz    case Primitive::kPrimFloat:
398d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz      array->AsFloatArray()->SetWithoutChecks<false>(index, static_cast<float>(value));
399d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz      break;
400d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz    case Primitive::kPrimLong:
401d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz      array->AsLongArray()->SetWithoutChecks<false>(index, static_cast<int64_t>(value));
402d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz      break;
403d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz    case Primitive::kPrimDouble:
404d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz      array->AsDoubleArray()->SetWithoutChecks<false>(index, static_cast<double>(value));
405d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz      break;
406d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz    case Primitive::kPrimNot: {
407d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz      mirror::ObjectArray<mirror::Object>* obj_array = array->AsObjectArray<mirror::Object>();
408d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz      obj_array->SetWithoutChecks<false>(index, reinterpret_cast<mirror::Object*>(
409d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz          static_cast<uintptr_t>(value)));
410d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz      break;
411d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz    }
412d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz    default:
413d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz      LOG(FATAL) << "Unsupported type " << array_type;
414d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz  }
415d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz}
416d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz
417d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertzvoid Transaction::ArrayLog::VisitRoots(RootCallback* callback, void* arg) {
418d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz  for (auto& it : array_values_) {
419d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz    mirror::Object* obj = reinterpret_cast<mirror::Object*>(static_cast<uintptr_t>(it.second));
420815873ecc312b1d231acce71e1a16f42cdaf09f2Mathieu Chartier    callback(&obj, arg, 0, kRootUnknown);
421815873ecc312b1d231acce71e1a16f42cdaf09f2Mathieu Chartier    it.second = reinterpret_cast<uintptr_t>(obj);
422d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz  }
423d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz}
424d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz
425d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz}  // namespace art
426