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());
87ee1d79a603c77c0667b27c075a983579d5c51f7eSebastien Hertz  DCHECK(!array->IsObjectArray());
88d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz  MutexLock mu(Thread::Current(), log_lock_);
89d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz  ArrayLog& array_log = array_logs_[array];
90d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz  array_log.LogValue(index, value);
91d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz}
92d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz
93d910fcef539e12ab181e56ec80684f39c4e95733Mathieu Chartiervoid Transaction::RecordStrongStringInsertion(mirror::String* s) {
94d910fcef539e12ab181e56ec80684f39c4e95733Mathieu Chartier  InternStringLog log(s, InternStringLog::kStrongString, InternStringLog::kInsert);
95d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz  LogInternedString(log);
96d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz}
97d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz
98d910fcef539e12ab181e56ec80684f39c4e95733Mathieu Chartiervoid Transaction::RecordWeakStringInsertion(mirror::String* s) {
99d910fcef539e12ab181e56ec80684f39c4e95733Mathieu Chartier  InternStringLog log(s, InternStringLog::kWeakString, InternStringLog::kInsert);
100d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz  LogInternedString(log);
101d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz}
102d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz
103d910fcef539e12ab181e56ec80684f39c4e95733Mathieu Chartiervoid Transaction::RecordStrongStringRemoval(mirror::String* s) {
104d910fcef539e12ab181e56ec80684f39c4e95733Mathieu Chartier  InternStringLog log(s, InternStringLog::kStrongString, InternStringLog::kRemove);
105d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz  LogInternedString(log);
106d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz}
107d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz
108d910fcef539e12ab181e56ec80684f39c4e95733Mathieu Chartiervoid Transaction::RecordWeakStringRemoval(mirror::String* s) {
109d910fcef539e12ab181e56ec80684f39c4e95733Mathieu Chartier  InternStringLog log(s, InternStringLog::kWeakString, InternStringLog::kRemove);
110d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz  LogInternedString(log);
111d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz}
112d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz
113d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertzvoid Transaction::LogInternedString(InternStringLog& log) {
114d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz  Locks::intern_table_lock_->AssertExclusiveHeld(Thread::Current());
115d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz  MutexLock mu(Thread::Current(), log_lock_);
116d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz  intern_string_logs_.push_front(log);
117d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz}
118d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz
119d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertzvoid Transaction::Abort() {
120d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz  CHECK(!Runtime::Current()->IsActiveTransaction());
121d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz  Thread* self = Thread::Current();
122d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz  self->AssertNoPendingException();
123d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz  MutexLock mu1(self, *Locks::intern_table_lock_);
124d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz  MutexLock mu2(self, log_lock_);
125d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz  UndoObjectModifications();
126d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz  UndoArrayModifications();
127d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz  UndoInternStringTableModifications();
128d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz}
129d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz
130d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertzvoid Transaction::UndoObjectModifications() {
131d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz  // TODO we may not need to restore objects allocated during this transaction. Or we could directly
132d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz  // remove them from the heap.
133d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz  for (auto it : object_logs_) {
134d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz    it.second.Undo(it.first);
135d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz  }
136d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz  object_logs_.clear();
137d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz}
138d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz
139d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertzvoid Transaction::UndoArrayModifications() {
140d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz  // TODO we may not need to restore array allocated during this transaction. Or we could directly
141d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz  // remove them from the heap.
142d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz  for (auto it : array_logs_) {
143d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz    it.second.Undo(it.first);
144d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz  }
145d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz  array_logs_.clear();
146d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz}
147d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz
148d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertzvoid Transaction::UndoInternStringTableModifications() {
149d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz  InternTable* const intern_table = Runtime::Current()->GetInternTable();
150d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz  // We want to undo each operation from the most recent to the oldest. List has been filled so the
151d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz  // most recent operation is at list begin so just have to iterate over it.
152d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz  for (InternStringLog& string_log : intern_string_logs_) {
153d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz    string_log.Undo(intern_table);
154d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz  }
155d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz  intern_string_logs_.clear();
156d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz}
157d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz
158d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertzvoid Transaction::VisitRoots(RootCallback* callback, void* arg) {
159d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz  MutexLock mu(Thread::Current(), log_lock_);
160d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz  VisitObjectLogs(callback, arg);
161d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz  VisitArrayLogs(callback, arg);
162d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz  VisitStringLogs(callback, arg);
163d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz}
164d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz
165d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertzvoid Transaction::VisitObjectLogs(RootCallback* callback, void* arg) {
166d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz  // List of moving roots.
167d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz  typedef std::pair<mirror::Object*, mirror::Object*> ObjectPair;
168d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz  std::list<ObjectPair> moving_roots;
169d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz
170d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz  // Visit roots.
171d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz  for (auto it : object_logs_) {
172d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz    it.second.VisitRoots(callback, arg);
173d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz    mirror::Object* old_root = it.first;
174815873ecc312b1d231acce71e1a16f42cdaf09f2Mathieu Chartier    mirror::Object* new_root = old_root;
17512f7423a2bb4bfab76700d84eb6d4338d211983aMathieu Chartier    callback(&new_root, arg, RootInfo(kRootUnknown));
176d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz    if (new_root != old_root) {
177d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz      moving_roots.push_back(std::make_pair(old_root, new_root));
178d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz    }
179d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz  }
180d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz
181d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz  // Update object logs with moving roots.
182d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz  for (const ObjectPair& pair : moving_roots) {
183d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz    mirror::Object* old_root = pair.first;
184d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz    mirror::Object* new_root = pair.second;
185d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz    auto old_root_it = object_logs_.find(old_root);
186d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz    CHECK(old_root_it != object_logs_.end());
187d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz    CHECK(object_logs_.find(new_root) == object_logs_.end());
188d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz    object_logs_.insert(std::make_pair(new_root, old_root_it->second));
189d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz    object_logs_.erase(old_root_it);
190d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz  }
191d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz}
192d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz
193d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertzvoid Transaction::VisitArrayLogs(RootCallback* callback, void* arg) {
194d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz  // List of moving roots.
195d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz  typedef std::pair<mirror::Array*, mirror::Array*> ArrayPair;
196d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz  std::list<ArrayPair> moving_roots;
197d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz
198d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz  for (auto it : array_logs_) {
199d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz    mirror::Array* old_root = it.first;
200ee1d79a603c77c0667b27c075a983579d5c51f7eSebastien Hertz    CHECK(!old_root->IsObjectArray());
201815873ecc312b1d231acce71e1a16f42cdaf09f2Mathieu Chartier    mirror::Array* new_root = old_root;
20212f7423a2bb4bfab76700d84eb6d4338d211983aMathieu Chartier    callback(reinterpret_cast<mirror::Object**>(&new_root), arg, RootInfo(kRootUnknown));
203d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz    if (new_root != old_root) {
204d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz      moving_roots.push_back(std::make_pair(old_root, new_root));
205d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz    }
206d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz  }
207d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz
208d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz  // Update array logs with moving roots.
209d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz  for (const ArrayPair& pair : moving_roots) {
210d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz    mirror::Array* old_root = pair.first;
211d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz    mirror::Array* new_root = pair.second;
212d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz    auto old_root_it = array_logs_.find(old_root);
213d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz    CHECK(old_root_it != array_logs_.end());
214d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz    CHECK(array_logs_.find(new_root) == array_logs_.end());
215d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz    array_logs_.insert(std::make_pair(new_root, old_root_it->second));
216d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz    array_logs_.erase(old_root_it);
217d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz  }
218d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz}
219d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz
220d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertzvoid Transaction::VisitStringLogs(RootCallback* callback, void* arg) {
221d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz  for (InternStringLog& log : intern_string_logs_) {
222d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz    log.VisitRoots(callback, arg);
223d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz  }
224d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz}
225d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz
226d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertzvoid Transaction::ObjectLog::Log32BitsValue(MemberOffset offset, uint32_t value, bool is_volatile) {
227d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz  auto it = field_values_.find(offset.Uint32Value());
228d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz  if (it == field_values_.end()) {
229d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz    ObjectLog::FieldValue field_value;
230d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz    field_value.value = value;
231d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz    field_value.is_volatile = is_volatile;
232d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz    field_value.kind = ObjectLog::k32Bits;
233d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz    field_values_.insert(std::make_pair(offset.Uint32Value(), field_value));
234d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz  }
235d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz}
236d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz
237d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertzvoid Transaction::ObjectLog::Log64BitsValue(MemberOffset offset, uint64_t value, bool is_volatile) {
238d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz  auto it = field_values_.find(offset.Uint32Value());
239d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz  if (it == field_values_.end()) {
240d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz    ObjectLog::FieldValue field_value;
241d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz    field_value.value = value;
242d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz    field_value.is_volatile = is_volatile;
243d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz    field_value.kind = ObjectLog::k64Bits;
244d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz    field_values_.insert(std::make_pair(offset.Uint32Value(), field_value));
245d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz  }
246d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz}
247d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz
248d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertzvoid Transaction::ObjectLog::LogReferenceValue(MemberOffset offset, mirror::Object* obj, bool is_volatile) {
249d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz  auto it = field_values_.find(offset.Uint32Value());
250d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz  if (it == field_values_.end()) {
251d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz    ObjectLog::FieldValue field_value;
252d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz    field_value.value = reinterpret_cast<uintptr_t>(obj);
253d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz    field_value.is_volatile = is_volatile;
254d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz    field_value.kind = ObjectLog::kReference;
255d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz    field_values_.insert(std::make_pair(offset.Uint32Value(), field_value));
256d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz  }
257d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz}
258d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz
259d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertzvoid Transaction::ObjectLog::Undo(mirror::Object* obj) {
260d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz  for (auto& it : field_values_) {
261d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz    // Garbage collector needs to access object's class and array's length. So we don't rollback
262d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz    // these values.
263d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz    MemberOffset field_offset(it.first);
264d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz    if (field_offset.Uint32Value() == mirror::Class::ClassOffset().Uint32Value()) {
265d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz      // Skip Object::class field.
266d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz      continue;
267d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz    }
268d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz    if (obj->IsArrayInstance() &&
269d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz        field_offset.Uint32Value() == mirror::Array::LengthOffset().Uint32Value()) {
270d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz      // Skip Array::length field.
271d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz      continue;
272d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz    }
273d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz    FieldValue& field_value = it.second;
274d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz    UndoFieldWrite(obj, field_offset, field_value);
275d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz  }
276d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz}
277d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz
278d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertzvoid Transaction::ObjectLog::UndoFieldWrite(mirror::Object* obj, MemberOffset field_offset,
279d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz                                            const FieldValue& field_value) {
280d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz  // TODO We may want to abort a transaction while still being in transaction mode. In this case,
281d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz  // we'd need to disable the check.
282d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz  constexpr bool kCheckTransaction = true;
283d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz  switch (field_value.kind) {
284d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz    case k32Bits:
285b0fa5dc7769c1e054032f39de0a3f6d6dd06f8cfIan Rogers      if (UNLIKELY(field_value.is_volatile)) {
286b0fa5dc7769c1e054032f39de0a3f6d6dd06f8cfIan Rogers        obj->SetField32Volatile<false, kCheckTransaction>(field_offset,
287b0fa5dc7769c1e054032f39de0a3f6d6dd06f8cfIan Rogers                                                          static_cast<uint32_t>(field_value.value));
288b0fa5dc7769c1e054032f39de0a3f6d6dd06f8cfIan Rogers      } else {
289b0fa5dc7769c1e054032f39de0a3f6d6dd06f8cfIan Rogers        obj->SetField32<false, kCheckTransaction>(field_offset,
290b0fa5dc7769c1e054032f39de0a3f6d6dd06f8cfIan Rogers                                                  static_cast<uint32_t>(field_value.value));
291b0fa5dc7769c1e054032f39de0a3f6d6dd06f8cfIan Rogers      }
292d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz      break;
293d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz    case k64Bits:
294b0fa5dc7769c1e054032f39de0a3f6d6dd06f8cfIan Rogers      if (UNLIKELY(field_value.is_volatile)) {
295b0fa5dc7769c1e054032f39de0a3f6d6dd06f8cfIan Rogers        obj->SetField64Volatile<false, kCheckTransaction>(field_offset, field_value.value);
296b0fa5dc7769c1e054032f39de0a3f6d6dd06f8cfIan Rogers      } else {
297b0fa5dc7769c1e054032f39de0a3f6d6dd06f8cfIan Rogers        obj->SetField64<false, kCheckTransaction>(field_offset, field_value.value);
298b0fa5dc7769c1e054032f39de0a3f6d6dd06f8cfIan Rogers      }
299d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz      break;
300d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz    case kReference:
301b0fa5dc7769c1e054032f39de0a3f6d6dd06f8cfIan Rogers      if (UNLIKELY(field_value.is_volatile)) {
302b0fa5dc7769c1e054032f39de0a3f6d6dd06f8cfIan Rogers        obj->SetFieldObjectVolatile<false, kCheckTransaction>(field_offset,
303b0fa5dc7769c1e054032f39de0a3f6d6dd06f8cfIan Rogers                                                              reinterpret_cast<mirror::Object*>(field_value.value));
304b0fa5dc7769c1e054032f39de0a3f6d6dd06f8cfIan Rogers      } else {
305b0fa5dc7769c1e054032f39de0a3f6d6dd06f8cfIan Rogers        obj->SetFieldObject<false, kCheckTransaction>(field_offset,
306b0fa5dc7769c1e054032f39de0a3f6d6dd06f8cfIan Rogers                                                      reinterpret_cast<mirror::Object*>(field_value.value));
307b0fa5dc7769c1e054032f39de0a3f6d6dd06f8cfIan Rogers      }
308d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz      break;
309d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz    default:
310d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz      LOG(FATAL) << "Unknown value kind " << field_value.kind;
311d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz      break;
312d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz  }
313d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz}
314d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz
315d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertzvoid Transaction::ObjectLog::VisitRoots(RootCallback* callback, void* arg) {
316d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz  for (auto it : field_values_) {
317d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz    FieldValue& field_value = it.second;
318d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz    if (field_value.kind == ObjectLog::kReference) {
319815873ecc312b1d231acce71e1a16f42cdaf09f2Mathieu Chartier      mirror::Object* obj =
320815873ecc312b1d231acce71e1a16f42cdaf09f2Mathieu Chartier          reinterpret_cast<mirror::Object*>(static_cast<uintptr_t>(field_value.value));
321a559ccb7aa56a5871b1e77857c2b5e7101b8d371Sebastien Hertz      if (obj != nullptr) {
32212f7423a2bb4bfab76700d84eb6d4338d211983aMathieu Chartier        callback(&obj, arg, RootInfo(kRootUnknown));
323a559ccb7aa56a5871b1e77857c2b5e7101b8d371Sebastien Hertz        field_value.value = reinterpret_cast<uintptr_t>(obj);
324a559ccb7aa56a5871b1e77857c2b5e7101b8d371Sebastien Hertz      }
325d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz    }
326d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz  }
327d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz}
328d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz
329d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertzvoid Transaction::InternStringLog::Undo(InternTable* intern_table) {
330d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz  DCHECK(intern_table != nullptr);
331d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz  switch (string_op_) {
332d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz      case InternStringLog::kInsert: {
333d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz        switch (string_kind_) {
334d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz          case InternStringLog::kStrongString:
335d910fcef539e12ab181e56ec80684f39c4e95733Mathieu Chartier            intern_table->RemoveStrongFromTransaction(str_);
336d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz            break;
337d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz          case InternStringLog::kWeakString:
338d910fcef539e12ab181e56ec80684f39c4e95733Mathieu Chartier            intern_table->RemoveWeakFromTransaction(str_);
339d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz            break;
340d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz          default:
341d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz            LOG(FATAL) << "Unknown interned string kind";
342d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz            break;
343d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz        }
344d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz        break;
345d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz      }
346d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz      case InternStringLog::kRemove: {
347d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz        switch (string_kind_) {
348d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz          case InternStringLog::kStrongString:
349d910fcef539e12ab181e56ec80684f39c4e95733Mathieu Chartier            intern_table->InsertStrongFromTransaction(str_);
350d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz            break;
351d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz          case InternStringLog::kWeakString:
352d910fcef539e12ab181e56ec80684f39c4e95733Mathieu Chartier            intern_table->InsertWeakFromTransaction(str_);
353d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz            break;
354d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz          default:
355d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz            LOG(FATAL) << "Unknown interned string kind";
356d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz            break;
357d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz        }
358d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz        break;
359d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz      }
360d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz      default:
361d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz        LOG(FATAL) << "Unknown interned string op";
362d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz        break;
363d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz    }
364d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz}
365d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz
366d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertzvoid Transaction::InternStringLog::VisitRoots(RootCallback* callback, void* arg) {
36712f7423a2bb4bfab76700d84eb6d4338d211983aMathieu Chartier  callback(reinterpret_cast<mirror::Object**>(&str_), arg, RootInfo(kRootInternedString));
368d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz}
369d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz
370d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertzvoid Transaction::ArrayLog::LogValue(size_t index, uint64_t value) {
371d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz  auto it = array_values_.find(index);
372d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz  if (it == array_values_.end()) {
373d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz    array_values_.insert(std::make_pair(index, value));
374d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz  }
375d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz}
376d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz
377d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertzvoid Transaction::ArrayLog::Undo(mirror::Array* array) {
378d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz  DCHECK(array != nullptr);
379d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz  DCHECK(array->IsArrayInstance());
380d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz  Primitive::Type type = array->GetClass()->GetComponentType()->GetPrimitiveType();
381d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz  for (auto it : array_values_) {
382d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz    UndoArrayWrite(array, type, it.first, it.second);
383d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz  }
384d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz}
385d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz
386d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertzvoid Transaction::ArrayLog::UndoArrayWrite(mirror::Array* array, Primitive::Type array_type,
387d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz                                           size_t index, uint64_t value) {
388d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz  // TODO We may want to abort a transaction while still being in transaction mode. In this case,
389d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz  // we'd need to disable the check.
390d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz  switch (array_type) {
391d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz    case Primitive::kPrimBoolean:
392d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz      array->AsBooleanArray()->SetWithoutChecks<false>(index, static_cast<uint8_t>(value));
393d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz      break;
394d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz    case Primitive::kPrimByte:
395d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz      array->AsByteArray()->SetWithoutChecks<false>(index, static_cast<int8_t>(value));
396d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz      break;
397d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz    case Primitive::kPrimChar:
398d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz      array->AsCharArray()->SetWithoutChecks<false>(index, static_cast<uint16_t>(value));
399d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz      break;
400d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz    case Primitive::kPrimShort:
401d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz      array->AsShortArray()->SetWithoutChecks<false>(index, static_cast<int16_t>(value));
402d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz      break;
403d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz    case Primitive::kPrimInt:
404d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz      array->AsIntArray()->SetWithoutChecks<false>(index, static_cast<int32_t>(value));
405d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz      break;
406d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz    case Primitive::kPrimFloat:
407d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz      array->AsFloatArray()->SetWithoutChecks<false>(index, static_cast<float>(value));
408d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz      break;
409d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz    case Primitive::kPrimLong:
410d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz      array->AsLongArray()->SetWithoutChecks<false>(index, static_cast<int64_t>(value));
411d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz      break;
412d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz    case Primitive::kPrimDouble:
413d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz      array->AsDoubleArray()->SetWithoutChecks<false>(index, static_cast<double>(value));
414d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz      break;
415ee1d79a603c77c0667b27c075a983579d5c51f7eSebastien Hertz    case Primitive::kPrimNot:
416ee1d79a603c77c0667b27c075a983579d5c51f7eSebastien Hertz      LOG(FATAL) << "ObjectArray should be treated as Object";
417d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz      break;
418d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz    default:
419d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz      LOG(FATAL) << "Unsupported type " << array_type;
420d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz  }
421d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz}
422d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz
423d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz}  // namespace art
424