blob: 50deb1f913dd094589871e380ae0d3c48e775828 [file] [log] [blame]
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +01001/*
2 * Copyright (C) 2014 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include "transaction.h"
18
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +010019#include "base/logging.h"
Andreas Gampe8cf9cb32017-07-19 09:28:38 -070020#include "base/stl_util.h"
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +010021#include "gc/accounting/card_table-inl.h"
Andreas Gampe508fdf32017-06-05 16:42:13 -070022#include "gc_root-inl.h"
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +010023#include "intern_table.h"
Mathieu Chartiere401d142015-04-22 13:56:20 -070024#include "mirror/class-inl.h"
Andreas Gampe508fdf32017-06-05 16:42:13 -070025#include "mirror/dex_cache-inl.h"
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +010026#include "mirror/object-inl.h"
27#include "mirror/object_array-inl.h"
28
29#include <list>
30
31namespace art {
32
33// TODO: remove (only used for debugging purpose).
34static constexpr bool kEnableTransactionStats = false;
35
Sebastien Hertz1c80bec2015-02-03 11:58:06 +010036Transaction::Transaction()
Chang Xing5a906fc2017-07-26 15:01:16 -070037 : log_lock_("transaction log lock", kTransactionLogLock),
38 aborted_(false),
Chang Xing605fe242017-07-20 15:57:21 -070039 rolling_back_(false),
Chang Xing5a906fc2017-07-26 15:01:16 -070040 strict_(false) {
Mathieu Chartiere5f13e52015-02-24 09:37:21 -080041 CHECK(Runtime::Current()->IsAotCompiler());
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +010042}
43
Chang Xing5a906fc2017-07-26 15:01:16 -070044Transaction::Transaction(bool strict, mirror::Class* root) : Transaction() {
45 strict_ = strict;
Chang Xingcade5c32017-07-20 17:56:26 -070046 root_ = root;
47}
48
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +010049Transaction::~Transaction() {
50 if (kEnableTransactionStats) {
51 MutexLock mu(Thread::Current(), log_lock_);
52 size_t objects_count = object_logs_.size();
53 size_t field_values_count = 0;
Mathieu Chartier38e954c2017-02-03 16:06:35 -080054 for (const auto& it : object_logs_) {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +010055 field_values_count += it.second.Size();
56 }
57 size_t array_count = array_logs_.size();
58 size_t array_values_count = 0;
Mathieu Chartier38e954c2017-02-03 16:06:35 -080059 for (const auto& it : array_logs_) {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +010060 array_values_count += it.second.Size();
61 }
Mathieu Chartierbb816d62016-09-07 10:17:46 -070062 size_t intern_string_count = intern_string_logs_.size();
63 size_t resolve_string_count = resolve_string_logs_.size();
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +010064 LOG(INFO) << "Transaction::~Transaction"
65 << ": objects_count=" << objects_count
66 << ", field_values_count=" << field_values_count
67 << ", array_count=" << array_count
68 << ", array_values_count=" << array_values_count
Mathieu Chartierbb816d62016-09-07 10:17:46 -070069 << ", intern_string_count=" << intern_string_count
70 << ", resolve_string_count=" << resolve_string_count;
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +010071 }
72}
73
Sebastien Hertz1c80bec2015-02-03 11:58:06 +010074void Transaction::Abort(const std::string& abort_message) {
75 MutexLock mu(Thread::Current(), log_lock_);
Sebastien Hertz2fd7e692015-04-02 11:11:19 +020076 // We may abort more than once if the exception thrown at the time of the
77 // previous abort has been caught during execution of a class initializer.
Sebastien Hertz1c80bec2015-02-03 11:58:06 +010078 // We just keep the message of the first abort because it will cause the
79 // transaction to be rolled back anyway.
80 if (!aborted_) {
81 aborted_ = true;
82 abort_message_ = abort_message;
83 }
84}
85
Sebastien Hertzb81e1cd2015-04-28 12:31:41 +020086void Transaction::ThrowAbortError(Thread* self, const std::string* abort_message) {
87 const bool rethrow = (abort_message == nullptr);
Sebastien Hertzbd9cf9f2015-03-03 12:16:13 +010088 if (kIsDebugBuild && rethrow) {
Sebastien Hertz2fd7e692015-04-02 11:11:19 +020089 CHECK(IsAborted()) << "Rethrow " << Transaction::kAbortExceptionDescriptor
90 << " while transaction is not aborted";
Sebastien Hertzbd9cf9f2015-03-03 12:16:13 +010091 }
Sebastien Hertzb81e1cd2015-04-28 12:31:41 +020092 if (rethrow) {
93 // Rethrow an exception with the earlier abort message stored in the transaction.
94 self->ThrowNewWrappedException(Transaction::kAbortExceptionSignature,
95 GetAbortMessage().c_str());
96 } else {
97 // Throw an exception with the given abort message.
98 self->ThrowNewWrappedException(Transaction::kAbortExceptionSignature,
99 abort_message->c_str());
100 }
Sebastien Hertz1c80bec2015-02-03 11:58:06 +0100101}
102
103bool Transaction::IsAborted() {
104 MutexLock mu(Thread::Current(), log_lock_);
105 return aborted_;
106}
107
Chang Xing605fe242017-07-20 15:57:21 -0700108bool Transaction::IsRollingBack() {
109 return rolling_back_;
110}
111
Chang Xing5a906fc2017-07-26 15:01:16 -0700112bool Transaction::IsStrict() {
113 MutexLock mu(Thread::Current(), log_lock_);
114 return strict_;
115}
116
Sebastien Hertz1c80bec2015-02-03 11:58:06 +0100117const std::string& Transaction::GetAbortMessage() {
118 MutexLock mu(Thread::Current(), log_lock_);
119 return abort_message_;
120}
121
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800122void Transaction::RecordWriteFieldBoolean(mirror::Object* obj,
123 MemberOffset field_offset,
124 uint8_t value,
125 bool is_volatile) {
Fred Shih37f05ef2014-07-16 18:38:08 -0700126 DCHECK(obj != nullptr);
127 MutexLock mu(Thread::Current(), log_lock_);
128 ObjectLog& object_log = object_logs_[obj];
129 object_log.LogBooleanValue(field_offset, value, is_volatile);
130}
131
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800132void Transaction::RecordWriteFieldByte(mirror::Object* obj,
133 MemberOffset field_offset,
134 int8_t value,
135 bool is_volatile) {
Fred Shih37f05ef2014-07-16 18:38:08 -0700136 DCHECK(obj != nullptr);
137 MutexLock mu(Thread::Current(), log_lock_);
138 ObjectLog& object_log = object_logs_[obj];
139 object_log.LogByteValue(field_offset, value, is_volatile);
140}
141
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800142void Transaction::RecordWriteFieldChar(mirror::Object* obj,
143 MemberOffset field_offset,
144 uint16_t value,
145 bool is_volatile) {
Fred Shih37f05ef2014-07-16 18:38:08 -0700146 DCHECK(obj != nullptr);
147 MutexLock mu(Thread::Current(), log_lock_);
148 ObjectLog& object_log = object_logs_[obj];
149 object_log.LogCharValue(field_offset, value, is_volatile);
150}
151
152
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800153void Transaction::RecordWriteFieldShort(mirror::Object* obj,
154 MemberOffset field_offset,
155 int16_t value,
156 bool is_volatile) {
Fred Shih37f05ef2014-07-16 18:38:08 -0700157 DCHECK(obj != nullptr);
158 MutexLock mu(Thread::Current(), log_lock_);
159 ObjectLog& object_log = object_logs_[obj];
160 object_log.LogShortValue(field_offset, value, is_volatile);
161}
162
163
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800164void Transaction::RecordWriteField32(mirror::Object* obj,
165 MemberOffset field_offset,
166 uint32_t value,
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100167 bool is_volatile) {
168 DCHECK(obj != nullptr);
169 MutexLock mu(Thread::Current(), log_lock_);
170 ObjectLog& object_log = object_logs_[obj];
171 object_log.Log32BitsValue(field_offset, value, is_volatile);
172}
173
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800174void Transaction::RecordWriteField64(mirror::Object* obj,
175 MemberOffset field_offset,
176 uint64_t value,
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100177 bool is_volatile) {
178 DCHECK(obj != nullptr);
179 MutexLock mu(Thread::Current(), log_lock_);
180 ObjectLog& object_log = object_logs_[obj];
181 object_log.Log64BitsValue(field_offset, value, is_volatile);
182}
183
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800184void Transaction::RecordWriteFieldReference(mirror::Object* obj,
185 MemberOffset field_offset,
186 mirror::Object* value,
187 bool is_volatile) {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100188 DCHECK(obj != nullptr);
189 MutexLock mu(Thread::Current(), log_lock_);
190 ObjectLog& object_log = object_logs_[obj];
191 object_log.LogReferenceValue(field_offset, value, is_volatile);
192}
193
194void Transaction::RecordWriteArray(mirror::Array* array, size_t index, uint64_t value) {
195 DCHECK(array != nullptr);
196 DCHECK(array->IsArrayInstance());
Sebastien Hertzee1d79a2014-02-21 15:46:30 +0100197 DCHECK(!array->IsObjectArray());
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100198 MutexLock mu(Thread::Current(), log_lock_);
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800199 auto it = array_logs_.find(array);
200 if (it == array_logs_.end()) {
201 ArrayLog log;
202 it = array_logs_.emplace(array, std::move(log)).first;
203 }
204 it->second.LogValue(index, value);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100205}
206
Andreas Gampe8a0128a2016-11-28 07:38:35 -0800207void Transaction::RecordResolveString(ObjPtr<mirror::DexCache> dex_cache,
208 dex::StringIndex string_idx) {
Mathieu Chartierbb816d62016-09-07 10:17:46 -0700209 DCHECK(dex_cache != nullptr);
Andreas Gampe8a0128a2016-11-28 07:38:35 -0800210 DCHECK_LT(string_idx.index_, dex_cache->GetDexFile()->NumStringIds());
Mathieu Chartierbb816d62016-09-07 10:17:46 -0700211 MutexLock mu(Thread::Current(), log_lock_);
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800212 resolve_string_logs_.emplace_back(dex_cache, string_idx);
Mathieu Chartierbb816d62016-09-07 10:17:46 -0700213}
214
Mathieu Chartier9e868092016-10-31 14:58:04 -0700215void Transaction::RecordStrongStringInsertion(ObjPtr<mirror::String> s) {
Mathieu Chartiercdfd39f2014-08-29 18:16:58 -0700216 InternStringLog log(s, InternStringLog::kStrongString, InternStringLog::kInsert);
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800217 LogInternedString(std::move(log));
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100218}
219
Mathieu Chartier9e868092016-10-31 14:58:04 -0700220void Transaction::RecordWeakStringInsertion(ObjPtr<mirror::String> s) {
Mathieu Chartiercdfd39f2014-08-29 18:16:58 -0700221 InternStringLog log(s, InternStringLog::kWeakString, InternStringLog::kInsert);
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800222 LogInternedString(std::move(log));
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100223}
224
Mathieu Chartier9e868092016-10-31 14:58:04 -0700225void Transaction::RecordStrongStringRemoval(ObjPtr<mirror::String> s) {
Mathieu Chartiercdfd39f2014-08-29 18:16:58 -0700226 InternStringLog log(s, InternStringLog::kStrongString, InternStringLog::kRemove);
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800227 LogInternedString(std::move(log));
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100228}
229
Mathieu Chartier9e868092016-10-31 14:58:04 -0700230void Transaction::RecordWeakStringRemoval(ObjPtr<mirror::String> s) {
Mathieu Chartiercdfd39f2014-08-29 18:16:58 -0700231 InternStringLog log(s, InternStringLog::kWeakString, InternStringLog::kRemove);
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800232 LogInternedString(std::move(log));
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100233}
234
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800235void Transaction::LogInternedString(InternStringLog&& log) {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100236 Locks::intern_table_lock_->AssertExclusiveHeld(Thread::Current());
237 MutexLock mu(Thread::Current(), log_lock_);
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800238 intern_string_logs_.push_front(std::move(log));
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100239}
240
Sebastien Hertz1c80bec2015-02-03 11:58:06 +0100241void Transaction::Rollback() {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100242 Thread* self = Thread::Current();
243 self->AssertNoPendingException();
244 MutexLock mu1(self, *Locks::intern_table_lock_);
245 MutexLock mu2(self, log_lock_);
Chang Xing605fe242017-07-20 15:57:21 -0700246 rolling_back_ = true;
247 CHECK(!Runtime::Current()->IsActiveTransaction());
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100248 UndoObjectModifications();
249 UndoArrayModifications();
250 UndoInternStringTableModifications();
Mathieu Chartierbb816d62016-09-07 10:17:46 -0700251 UndoResolveStringModifications();
Chang Xing605fe242017-07-20 15:57:21 -0700252 rolling_back_ = false;
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100253}
254
255void Transaction::UndoObjectModifications() {
256 // TODO we may not need to restore objects allocated during this transaction. Or we could directly
257 // remove them from the heap.
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800258 for (const auto& it : object_logs_) {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100259 it.second.Undo(it.first);
260 }
261 object_logs_.clear();
262}
263
264void Transaction::UndoArrayModifications() {
265 // TODO we may not need to restore array allocated during this transaction. Or we could directly
266 // remove them from the heap.
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800267 for (const auto& it : array_logs_) {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100268 it.second.Undo(it.first);
269 }
270 array_logs_.clear();
271}
272
273void Transaction::UndoInternStringTableModifications() {
274 InternTable* const intern_table = Runtime::Current()->GetInternTable();
275 // We want to undo each operation from the most recent to the oldest. List has been filled so the
276 // most recent operation is at list begin so just have to iterate over it.
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800277 for (const InternStringLog& string_log : intern_string_logs_) {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100278 string_log.Undo(intern_table);
279 }
280 intern_string_logs_.clear();
281}
282
Mathieu Chartierbb816d62016-09-07 10:17:46 -0700283void Transaction::UndoResolveStringModifications() {
284 for (ResolveStringLog& string_log : resolve_string_logs_) {
285 string_log.Undo();
286 }
287 resolve_string_logs_.clear();
288}
289
Mathieu Chartierbb87e0f2015-04-03 11:21:55 -0700290void Transaction::VisitRoots(RootVisitor* visitor) {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100291 MutexLock mu(Thread::Current(), log_lock_);
Chang Xingcade5c32017-07-20 17:56:26 -0700292 visitor->VisitRoot(reinterpret_cast<mirror::Object**>(&root_), RootInfo(kRootUnknown));
Mathieu Chartierbb87e0f2015-04-03 11:21:55 -0700293 VisitObjectLogs(visitor);
294 VisitArrayLogs(visitor);
Mathieu Chartierbb816d62016-09-07 10:17:46 -0700295 VisitInternStringLogs(visitor);
296 VisitResolveStringLogs(visitor);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100297}
298
Mathieu Chartierbb87e0f2015-04-03 11:21:55 -0700299void Transaction::VisitObjectLogs(RootVisitor* visitor) {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100300 // List of moving roots.
301 typedef std::pair<mirror::Object*, mirror::Object*> ObjectPair;
302 std::list<ObjectPair> moving_roots;
303
304 // Visit roots.
Mathieu Chartier5f257b12017-02-03 14:47:36 -0800305 for (auto& it : object_logs_) {
Mathieu Chartierbb87e0f2015-04-03 11:21:55 -0700306 it.second.VisitRoots(visitor);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100307 mirror::Object* old_root = it.first;
Mathieu Chartier815873e2014-02-13 18:02:13 -0800308 mirror::Object* new_root = old_root;
Mathieu Chartierbb87e0f2015-04-03 11:21:55 -0700309 visitor->VisitRoot(&new_root, RootInfo(kRootUnknown));
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100310 if (new_root != old_root) {
311 moving_roots.push_back(std::make_pair(old_root, new_root));
312 }
313 }
314
315 // Update object logs with moving roots.
316 for (const ObjectPair& pair : moving_roots) {
317 mirror::Object* old_root = pair.first;
318 mirror::Object* new_root = pair.second;
319 auto old_root_it = object_logs_.find(old_root);
320 CHECK(old_root_it != object_logs_.end());
321 CHECK(object_logs_.find(new_root) == object_logs_.end());
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800322 object_logs_.emplace(new_root, std::move(old_root_it->second));
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100323 object_logs_.erase(old_root_it);
324 }
325}
326
Mathieu Chartierbb87e0f2015-04-03 11:21:55 -0700327void Transaction::VisitArrayLogs(RootVisitor* visitor) {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100328 // List of moving roots.
329 typedef std::pair<mirror::Array*, mirror::Array*> ArrayPair;
330 std::list<ArrayPair> moving_roots;
331
Mathieu Chartier5f257b12017-02-03 14:47:36 -0800332 for (auto& it : array_logs_) {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100333 mirror::Array* old_root = it.first;
Sebastien Hertzee1d79a2014-02-21 15:46:30 +0100334 CHECK(!old_root->IsObjectArray());
Mathieu Chartier815873e2014-02-13 18:02:13 -0800335 mirror::Array* new_root = old_root;
Mathieu Chartierbb87e0f2015-04-03 11:21:55 -0700336 visitor->VisitRoot(reinterpret_cast<mirror::Object**>(&new_root), RootInfo(kRootUnknown));
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100337 if (new_root != old_root) {
338 moving_roots.push_back(std::make_pair(old_root, new_root));
339 }
340 }
341
342 // Update array logs with moving roots.
343 for (const ArrayPair& pair : moving_roots) {
344 mirror::Array* old_root = pair.first;
345 mirror::Array* new_root = pair.second;
346 auto old_root_it = array_logs_.find(old_root);
347 CHECK(old_root_it != array_logs_.end());
348 CHECK(array_logs_.find(new_root) == array_logs_.end());
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800349 array_logs_.emplace(new_root, std::move(old_root_it->second));
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100350 array_logs_.erase(old_root_it);
351 }
352}
353
Mathieu Chartierbb816d62016-09-07 10:17:46 -0700354void Transaction::VisitInternStringLogs(RootVisitor* visitor) {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100355 for (InternStringLog& log : intern_string_logs_) {
Mathieu Chartierbb87e0f2015-04-03 11:21:55 -0700356 log.VisitRoots(visitor);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100357 }
358}
359
Mathieu Chartierbb816d62016-09-07 10:17:46 -0700360void Transaction::VisitResolveStringLogs(RootVisitor* visitor) {
361 for (ResolveStringLog& log : resolve_string_logs_) {
362 log.VisitRoots(visitor);
363 }
364}
365
Fred Shih37f05ef2014-07-16 18:38:08 -0700366void Transaction::ObjectLog::LogBooleanValue(MemberOffset offset, uint8_t value, bool is_volatile) {
367 LogValue(ObjectLog::kBoolean, offset, value, is_volatile);
368}
369
370void Transaction::ObjectLog::LogByteValue(MemberOffset offset, int8_t value, bool is_volatile) {
371 LogValue(ObjectLog::kByte, offset, value, is_volatile);
372}
373
374void Transaction::ObjectLog::LogCharValue(MemberOffset offset, uint16_t value, bool is_volatile) {
375 LogValue(ObjectLog::kChar, offset, value, is_volatile);
376}
377
378void Transaction::ObjectLog::LogShortValue(MemberOffset offset, int16_t value, bool is_volatile) {
379 LogValue(ObjectLog::kShort, offset, value, is_volatile);
380}
381
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100382void Transaction::ObjectLog::Log32BitsValue(MemberOffset offset, uint32_t value, bool is_volatile) {
Fred Shih37f05ef2014-07-16 18:38:08 -0700383 LogValue(ObjectLog::k32Bits, offset, value, is_volatile);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100384}
385
386void Transaction::ObjectLog::Log64BitsValue(MemberOffset offset, uint64_t value, bool is_volatile) {
Fred Shih37f05ef2014-07-16 18:38:08 -0700387 LogValue(ObjectLog::k64Bits, offset, value, is_volatile);
388}
389
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800390void Transaction::ObjectLog::LogReferenceValue(MemberOffset offset,
391 mirror::Object* obj,
392 bool is_volatile) {
Fred Shih37f05ef2014-07-16 18:38:08 -0700393 LogValue(ObjectLog::kReference, offset, reinterpret_cast<uintptr_t>(obj), is_volatile);
394}
395
396void Transaction::ObjectLog::LogValue(ObjectLog::FieldValueKind kind,
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800397 MemberOffset offset,
398 uint64_t value,
399 bool is_volatile) {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100400 auto it = field_values_.find(offset.Uint32Value());
401 if (it == field_values_.end()) {
402 ObjectLog::FieldValue field_value;
403 field_value.value = value;
404 field_value.is_volatile = is_volatile;
Fred Shih37f05ef2014-07-16 18:38:08 -0700405 field_value.kind = kind;
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800406 field_values_.emplace(offset.Uint32Value(), std::move(field_value));
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100407 }
408}
409
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800410void Transaction::ObjectLog::Undo(mirror::Object* obj) const {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100411 for (auto& it : field_values_) {
412 // Garbage collector needs to access object's class and array's length. So we don't rollback
413 // these values.
414 MemberOffset field_offset(it.first);
415 if (field_offset.Uint32Value() == mirror::Class::ClassOffset().Uint32Value()) {
416 // Skip Object::class field.
417 continue;
418 }
419 if (obj->IsArrayInstance() &&
420 field_offset.Uint32Value() == mirror::Array::LengthOffset().Uint32Value()) {
421 // Skip Array::length field.
422 continue;
423 }
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800424 const FieldValue& field_value = it.second;
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100425 UndoFieldWrite(obj, field_offset, field_value);
426 }
427}
428
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800429void Transaction::ObjectLog::UndoFieldWrite(mirror::Object* obj,
430 MemberOffset field_offset,
431 const FieldValue& field_value) const {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100432 // TODO We may want to abort a transaction while still being in transaction mode. In this case,
433 // we'd need to disable the check.
Chang Xing605fe242017-07-20 15:57:21 -0700434 constexpr bool kCheckTransaction = false;
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100435 switch (field_value.kind) {
Fred Shih37f05ef2014-07-16 18:38:08 -0700436 case kBoolean:
437 if (UNLIKELY(field_value.is_volatile)) {
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800438 obj->SetFieldBooleanVolatile<false, kCheckTransaction>(
439 field_offset,
440 static_cast<bool>(field_value.value));
Fred Shih37f05ef2014-07-16 18:38:08 -0700441 } else {
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800442 obj->SetFieldBoolean<false, kCheckTransaction>(
443 field_offset,
444 static_cast<bool>(field_value.value));
Fred Shih37f05ef2014-07-16 18:38:08 -0700445 }
446 break;
447 case kByte:
448 if (UNLIKELY(field_value.is_volatile)) {
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800449 obj->SetFieldByteVolatile<false, kCheckTransaction>(
450 field_offset,
451 static_cast<int8_t>(field_value.value));
Fred Shih37f05ef2014-07-16 18:38:08 -0700452 } else {
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800453 obj->SetFieldByte<false, kCheckTransaction>(
454 field_offset,
455 static_cast<int8_t>(field_value.value));
Fred Shih37f05ef2014-07-16 18:38:08 -0700456 }
457 break;
458 case kChar:
459 if (UNLIKELY(field_value.is_volatile)) {
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800460 obj->SetFieldCharVolatile<false, kCheckTransaction>(
461 field_offset,
462 static_cast<uint16_t>(field_value.value));
Fred Shih37f05ef2014-07-16 18:38:08 -0700463 } else {
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800464 obj->SetFieldChar<false, kCheckTransaction>(
465 field_offset,
466 static_cast<uint16_t>(field_value.value));
Fred Shih37f05ef2014-07-16 18:38:08 -0700467 }
468 break;
469 case kShort:
470 if (UNLIKELY(field_value.is_volatile)) {
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800471 obj->SetFieldShortVolatile<false, kCheckTransaction>(
472 field_offset,
473 static_cast<int16_t>(field_value.value));
Fred Shih37f05ef2014-07-16 18:38:08 -0700474 } else {
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800475 obj->SetFieldShort<false, kCheckTransaction>(
476 field_offset,
477 static_cast<int16_t>(field_value.value));
Fred Shih37f05ef2014-07-16 18:38:08 -0700478 }
479 break;
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100480 case k32Bits:
Ian Rogersb0fa5dc2014-04-28 16:47:08 -0700481 if (UNLIKELY(field_value.is_volatile)) {
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800482 obj->SetField32Volatile<false, kCheckTransaction>(
483 field_offset,
484 static_cast<uint32_t>(field_value.value));
Ian Rogersb0fa5dc2014-04-28 16:47:08 -0700485 } else {
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800486 obj->SetField32<false, kCheckTransaction>(
487 field_offset,
488 static_cast<uint32_t>(field_value.value));
Ian Rogersb0fa5dc2014-04-28 16:47:08 -0700489 }
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100490 break;
491 case k64Bits:
Ian Rogersb0fa5dc2014-04-28 16:47:08 -0700492 if (UNLIKELY(field_value.is_volatile)) {
493 obj->SetField64Volatile<false, kCheckTransaction>(field_offset, field_value.value);
494 } else {
495 obj->SetField64<false, kCheckTransaction>(field_offset, field_value.value);
496 }
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100497 break;
498 case kReference:
Ian Rogersb0fa5dc2014-04-28 16:47:08 -0700499 if (UNLIKELY(field_value.is_volatile)) {
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800500 obj->SetFieldObjectVolatile<false, kCheckTransaction>(
501 field_offset,
502 reinterpret_cast<mirror::Object*>(field_value.value));
Ian Rogersb0fa5dc2014-04-28 16:47:08 -0700503 } else {
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800504 obj->SetFieldObject<false, kCheckTransaction>(
505 field_offset,
506 reinterpret_cast<mirror::Object*>(field_value.value));
Ian Rogersb0fa5dc2014-04-28 16:47:08 -0700507 }
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100508 break;
509 default:
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700510 LOG(FATAL) << "Unknown value kind " << static_cast<int>(field_value.kind);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100511 break;
512 }
513}
514
Mathieu Chartierbb87e0f2015-04-03 11:21:55 -0700515void Transaction::ObjectLog::VisitRoots(RootVisitor* visitor) {
Mathieu Chartier5f257b12017-02-03 14:47:36 -0800516 for (auto& it : field_values_) {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100517 FieldValue& field_value = it.second;
518 if (field_value.kind == ObjectLog::kReference) {
Mathieu Chartierbb87e0f2015-04-03 11:21:55 -0700519 visitor->VisitRootIfNonNull(reinterpret_cast<mirror::Object**>(&field_value.value),
520 RootInfo(kRootUnknown));
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100521 }
522 }
523}
524
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800525void Transaction::InternStringLog::Undo(InternTable* intern_table) const {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100526 DCHECK(intern_table != nullptr);
527 switch (string_op_) {
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700528 case InternStringLog::kInsert: {
529 switch (string_kind_) {
530 case InternStringLog::kStrongString:
Mathieu Chartier9e868092016-10-31 14:58:04 -0700531 intern_table->RemoveStrongFromTransaction(str_.Read());
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700532 break;
533 case InternStringLog::kWeakString:
Mathieu Chartier9e868092016-10-31 14:58:04 -0700534 intern_table->RemoveWeakFromTransaction(str_.Read());
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700535 break;
536 default:
537 LOG(FATAL) << "Unknown interned string kind";
538 break;
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100539 }
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700540 break;
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100541 }
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700542 case InternStringLog::kRemove: {
543 switch (string_kind_) {
544 case InternStringLog::kStrongString:
Mathieu Chartier9e868092016-10-31 14:58:04 -0700545 intern_table->InsertStrongFromTransaction(str_.Read());
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700546 break;
547 case InternStringLog::kWeakString:
Mathieu Chartier9e868092016-10-31 14:58:04 -0700548 intern_table->InsertWeakFromTransaction(str_.Read());
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700549 break;
550 default:
551 LOG(FATAL) << "Unknown interned string kind";
552 break;
553 }
554 break;
555 }
556 default:
557 LOG(FATAL) << "Unknown interned string op";
558 break;
559 }
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100560}
561
Mathieu Chartierbb87e0f2015-04-03 11:21:55 -0700562void Transaction::InternStringLog::VisitRoots(RootVisitor* visitor) {
Mathieu Chartier9e868092016-10-31 14:58:04 -0700563 str_.VisitRoot(visitor, RootInfo(kRootInternedString));
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100564}
565
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800566void Transaction::ResolveStringLog::Undo() const {
Mathieu Chartierbb816d62016-09-07 10:17:46 -0700567 dex_cache_.Read()->ClearString(string_idx_);
568}
569
Mathieu Chartier9e868092016-10-31 14:58:04 -0700570Transaction::ResolveStringLog::ResolveStringLog(ObjPtr<mirror::DexCache> dex_cache,
Andreas Gampe8a0128a2016-11-28 07:38:35 -0800571 dex::StringIndex string_idx)
Mathieu Chartierbb816d62016-09-07 10:17:46 -0700572 : dex_cache_(dex_cache),
573 string_idx_(string_idx) {
574 DCHECK(dex_cache != nullptr);
Andreas Gampe8a0128a2016-11-28 07:38:35 -0800575 DCHECK_LT(string_idx_.index_, dex_cache->GetDexFile()->NumStringIds());
Mathieu Chartierbb816d62016-09-07 10:17:46 -0700576}
577
578void Transaction::ResolveStringLog::VisitRoots(RootVisitor* visitor) {
579 dex_cache_.VisitRoot(visitor, RootInfo(kRootVMInternal));
580}
581
Mathieu Chartier9e868092016-10-31 14:58:04 -0700582Transaction::InternStringLog::InternStringLog(ObjPtr<mirror::String> s,
583 StringKind kind,
584 StringOp op)
585 : str_(s),
586 string_kind_(kind),
587 string_op_(op) {
588 DCHECK(s != nullptr);
589}
590
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100591void Transaction::ArrayLog::LogValue(size_t index, uint64_t value) {
592 auto it = array_values_.find(index);
593 if (it == array_values_.end()) {
594 array_values_.insert(std::make_pair(index, value));
595 }
596}
597
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800598void Transaction::ArrayLog::Undo(mirror::Array* array) const {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100599 DCHECK(array != nullptr);
600 DCHECK(array->IsArrayInstance());
601 Primitive::Type type = array->GetClass()->GetComponentType()->GetPrimitiveType();
602 for (auto it : array_values_) {
603 UndoArrayWrite(array, type, it.first, it.second);
604 }
605}
606
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800607void Transaction::ArrayLog::UndoArrayWrite(mirror::Array* array,
608 Primitive::Type array_type,
609 size_t index,
610 uint64_t value) const {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100611 // TODO We may want to abort a transaction while still being in transaction mode. In this case,
612 // we'd need to disable the check.
Chang Xing605fe242017-07-20 15:57:21 -0700613 constexpr bool kCheckTransaction = false;
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100614 switch (array_type) {
615 case Primitive::kPrimBoolean:
Chang Xing605fe242017-07-20 15:57:21 -0700616 array->AsBooleanArray()->SetWithoutChecks<false, kCheckTransaction>(
617 index, static_cast<uint8_t>(value));
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100618 break;
619 case Primitive::kPrimByte:
Chang Xing605fe242017-07-20 15:57:21 -0700620 array->AsByteArray()->SetWithoutChecks<false, kCheckTransaction>(
621 index, static_cast<int8_t>(value));
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100622 break;
623 case Primitive::kPrimChar:
Chang Xing605fe242017-07-20 15:57:21 -0700624 array->AsCharArray()->SetWithoutChecks<false, kCheckTransaction>(
625 index, static_cast<uint16_t>(value));
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100626 break;
627 case Primitive::kPrimShort:
Chang Xing605fe242017-07-20 15:57:21 -0700628 array->AsShortArray()->SetWithoutChecks<false, kCheckTransaction>(
629 index, static_cast<int16_t>(value));
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100630 break;
631 case Primitive::kPrimInt:
Chang Xing605fe242017-07-20 15:57:21 -0700632 array->AsIntArray()->SetWithoutChecks<false, kCheckTransaction>(
633 index, static_cast<int32_t>(value));
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100634 break;
635 case Primitive::kPrimFloat:
Chang Xing605fe242017-07-20 15:57:21 -0700636 array->AsFloatArray()->SetWithoutChecks<false, kCheckTransaction>(
637 index, static_cast<float>(value));
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100638 break;
639 case Primitive::kPrimLong:
Chang Xing605fe242017-07-20 15:57:21 -0700640 array->AsLongArray()->SetWithoutChecks<false, kCheckTransaction>(
641 index, static_cast<int64_t>(value));
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100642 break;
643 case Primitive::kPrimDouble:
Chang Xing605fe242017-07-20 15:57:21 -0700644 array->AsDoubleArray()->SetWithoutChecks<false, kCheckTransaction>(
645 index, static_cast<double>(value));
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100646 break;
Sebastien Hertzee1d79a2014-02-21 15:46:30 +0100647 case Primitive::kPrimNot:
648 LOG(FATAL) << "ObjectArray should be treated as Object";
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100649 break;
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100650 default:
651 LOG(FATAL) << "Unsupported type " << array_type;
652 }
653}
654
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100655} // namespace art