blob: 9e62aa6b553bdd2d5e943d486d57c53edeed21cd [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()
37 : log_lock_("transaction log lock", kTransactionLogLock), aborted_(false) {
Mathieu Chartiere5f13e52015-02-24 09:37:21 -080038 CHECK(Runtime::Current()->IsAotCompiler());
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +010039}
40
Chang Xingcade5c32017-07-20 17:56:26 -070041Transaction::Transaction(mirror::Class* root) : Transaction() {
42 root_ = root;
43}
44
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +010045Transaction::~Transaction() {
46 if (kEnableTransactionStats) {
47 MutexLock mu(Thread::Current(), log_lock_);
48 size_t objects_count = object_logs_.size();
49 size_t field_values_count = 0;
Mathieu Chartier38e954c2017-02-03 16:06:35 -080050 for (const auto& it : object_logs_) {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +010051 field_values_count += it.second.Size();
52 }
53 size_t array_count = array_logs_.size();
54 size_t array_values_count = 0;
Mathieu Chartier38e954c2017-02-03 16:06:35 -080055 for (const auto& it : array_logs_) {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +010056 array_values_count += it.second.Size();
57 }
Mathieu Chartierbb816d62016-09-07 10:17:46 -070058 size_t intern_string_count = intern_string_logs_.size();
59 size_t resolve_string_count = resolve_string_logs_.size();
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +010060 LOG(INFO) << "Transaction::~Transaction"
61 << ": objects_count=" << objects_count
62 << ", field_values_count=" << field_values_count
63 << ", array_count=" << array_count
64 << ", array_values_count=" << array_values_count
Mathieu Chartierbb816d62016-09-07 10:17:46 -070065 << ", intern_string_count=" << intern_string_count
66 << ", resolve_string_count=" << resolve_string_count;
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +010067 }
68}
69
Sebastien Hertz1c80bec2015-02-03 11:58:06 +010070void Transaction::Abort(const std::string& abort_message) {
71 MutexLock mu(Thread::Current(), log_lock_);
Sebastien Hertz2fd7e692015-04-02 11:11:19 +020072 // We may abort more than once if the exception thrown at the time of the
73 // previous abort has been caught during execution of a class initializer.
Sebastien Hertz1c80bec2015-02-03 11:58:06 +010074 // We just keep the message of the first abort because it will cause the
75 // transaction to be rolled back anyway.
76 if (!aborted_) {
77 aborted_ = true;
78 abort_message_ = abort_message;
79 }
80}
81
Sebastien Hertzb81e1cd2015-04-28 12:31:41 +020082void Transaction::ThrowAbortError(Thread* self, const std::string* abort_message) {
83 const bool rethrow = (abort_message == nullptr);
Sebastien Hertzbd9cf9f2015-03-03 12:16:13 +010084 if (kIsDebugBuild && rethrow) {
Sebastien Hertz2fd7e692015-04-02 11:11:19 +020085 CHECK(IsAborted()) << "Rethrow " << Transaction::kAbortExceptionDescriptor
86 << " while transaction is not aborted";
Sebastien Hertzbd9cf9f2015-03-03 12:16:13 +010087 }
Sebastien Hertzb81e1cd2015-04-28 12:31:41 +020088 if (rethrow) {
89 // Rethrow an exception with the earlier abort message stored in the transaction.
90 self->ThrowNewWrappedException(Transaction::kAbortExceptionSignature,
91 GetAbortMessage().c_str());
92 } else {
93 // Throw an exception with the given abort message.
94 self->ThrowNewWrappedException(Transaction::kAbortExceptionSignature,
95 abort_message->c_str());
96 }
Sebastien Hertz1c80bec2015-02-03 11:58:06 +010097}
98
99bool Transaction::IsAborted() {
100 MutexLock mu(Thread::Current(), log_lock_);
101 return aborted_;
102}
103
104const std::string& Transaction::GetAbortMessage() {
105 MutexLock mu(Thread::Current(), log_lock_);
106 return abort_message_;
107}
108
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800109void Transaction::RecordWriteFieldBoolean(mirror::Object* obj,
110 MemberOffset field_offset,
111 uint8_t value,
112 bool is_volatile) {
Fred Shih37f05ef2014-07-16 18:38:08 -0700113 DCHECK(obj != nullptr);
114 MutexLock mu(Thread::Current(), log_lock_);
115 ObjectLog& object_log = object_logs_[obj];
116 object_log.LogBooleanValue(field_offset, value, is_volatile);
117}
118
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800119void Transaction::RecordWriteFieldByte(mirror::Object* obj,
120 MemberOffset field_offset,
121 int8_t value,
122 bool is_volatile) {
Fred Shih37f05ef2014-07-16 18:38:08 -0700123 DCHECK(obj != nullptr);
124 MutexLock mu(Thread::Current(), log_lock_);
125 ObjectLog& object_log = object_logs_[obj];
126 object_log.LogByteValue(field_offset, value, is_volatile);
127}
128
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800129void Transaction::RecordWriteFieldChar(mirror::Object* obj,
130 MemberOffset field_offset,
131 uint16_t value,
132 bool is_volatile) {
Fred Shih37f05ef2014-07-16 18:38:08 -0700133 DCHECK(obj != nullptr);
134 MutexLock mu(Thread::Current(), log_lock_);
135 ObjectLog& object_log = object_logs_[obj];
136 object_log.LogCharValue(field_offset, value, is_volatile);
137}
138
139
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800140void Transaction::RecordWriteFieldShort(mirror::Object* obj,
141 MemberOffset field_offset,
142 int16_t value,
143 bool is_volatile) {
Fred Shih37f05ef2014-07-16 18:38:08 -0700144 DCHECK(obj != nullptr);
145 MutexLock mu(Thread::Current(), log_lock_);
146 ObjectLog& object_log = object_logs_[obj];
147 object_log.LogShortValue(field_offset, value, is_volatile);
148}
149
150
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800151void Transaction::RecordWriteField32(mirror::Object* obj,
152 MemberOffset field_offset,
153 uint32_t value,
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100154 bool is_volatile) {
155 DCHECK(obj != nullptr);
156 MutexLock mu(Thread::Current(), log_lock_);
157 ObjectLog& object_log = object_logs_[obj];
158 object_log.Log32BitsValue(field_offset, value, is_volatile);
159}
160
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800161void Transaction::RecordWriteField64(mirror::Object* obj,
162 MemberOffset field_offset,
163 uint64_t value,
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100164 bool is_volatile) {
165 DCHECK(obj != nullptr);
166 MutexLock mu(Thread::Current(), log_lock_);
167 ObjectLog& object_log = object_logs_[obj];
168 object_log.Log64BitsValue(field_offset, value, is_volatile);
169}
170
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800171void Transaction::RecordWriteFieldReference(mirror::Object* obj,
172 MemberOffset field_offset,
173 mirror::Object* value,
174 bool is_volatile) {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100175 DCHECK(obj != nullptr);
176 MutexLock mu(Thread::Current(), log_lock_);
177 ObjectLog& object_log = object_logs_[obj];
178 object_log.LogReferenceValue(field_offset, value, is_volatile);
179}
180
181void Transaction::RecordWriteArray(mirror::Array* array, size_t index, uint64_t value) {
182 DCHECK(array != nullptr);
183 DCHECK(array->IsArrayInstance());
Sebastien Hertzee1d79a2014-02-21 15:46:30 +0100184 DCHECK(!array->IsObjectArray());
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100185 MutexLock mu(Thread::Current(), log_lock_);
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800186 auto it = array_logs_.find(array);
187 if (it == array_logs_.end()) {
188 ArrayLog log;
189 it = array_logs_.emplace(array, std::move(log)).first;
190 }
191 it->second.LogValue(index, value);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100192}
193
Andreas Gampe8a0128a2016-11-28 07:38:35 -0800194void Transaction::RecordResolveString(ObjPtr<mirror::DexCache> dex_cache,
195 dex::StringIndex string_idx) {
Mathieu Chartierbb816d62016-09-07 10:17:46 -0700196 DCHECK(dex_cache != nullptr);
Andreas Gampe8a0128a2016-11-28 07:38:35 -0800197 DCHECK_LT(string_idx.index_, dex_cache->GetDexFile()->NumStringIds());
Mathieu Chartierbb816d62016-09-07 10:17:46 -0700198 MutexLock mu(Thread::Current(), log_lock_);
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800199 resolve_string_logs_.emplace_back(dex_cache, string_idx);
Mathieu Chartierbb816d62016-09-07 10:17:46 -0700200}
201
Mathieu Chartier9e868092016-10-31 14:58:04 -0700202void Transaction::RecordStrongStringInsertion(ObjPtr<mirror::String> s) {
Mathieu Chartiercdfd39f2014-08-29 18:16:58 -0700203 InternStringLog log(s, InternStringLog::kStrongString, InternStringLog::kInsert);
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800204 LogInternedString(std::move(log));
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100205}
206
Mathieu Chartier9e868092016-10-31 14:58:04 -0700207void Transaction::RecordWeakStringInsertion(ObjPtr<mirror::String> s) {
Mathieu Chartiercdfd39f2014-08-29 18:16:58 -0700208 InternStringLog log(s, InternStringLog::kWeakString, InternStringLog::kInsert);
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800209 LogInternedString(std::move(log));
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100210}
211
Mathieu Chartier9e868092016-10-31 14:58:04 -0700212void Transaction::RecordStrongStringRemoval(ObjPtr<mirror::String> s) {
Mathieu Chartiercdfd39f2014-08-29 18:16:58 -0700213 InternStringLog log(s, InternStringLog::kStrongString, InternStringLog::kRemove);
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800214 LogInternedString(std::move(log));
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100215}
216
Mathieu Chartier9e868092016-10-31 14:58:04 -0700217void Transaction::RecordWeakStringRemoval(ObjPtr<mirror::String> s) {
Mathieu Chartiercdfd39f2014-08-29 18:16:58 -0700218 InternStringLog log(s, InternStringLog::kWeakString, InternStringLog::kRemove);
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800219 LogInternedString(std::move(log));
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100220}
221
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800222void Transaction::LogInternedString(InternStringLog&& log) {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100223 Locks::intern_table_lock_->AssertExclusiveHeld(Thread::Current());
224 MutexLock mu(Thread::Current(), log_lock_);
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800225 intern_string_logs_.push_front(std::move(log));
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100226}
227
Sebastien Hertz1c80bec2015-02-03 11:58:06 +0100228void Transaction::Rollback() {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100229 CHECK(!Runtime::Current()->IsActiveTransaction());
230 Thread* self = Thread::Current();
231 self->AssertNoPendingException();
232 MutexLock mu1(self, *Locks::intern_table_lock_);
233 MutexLock mu2(self, log_lock_);
234 UndoObjectModifications();
235 UndoArrayModifications();
236 UndoInternStringTableModifications();
Mathieu Chartierbb816d62016-09-07 10:17:46 -0700237 UndoResolveStringModifications();
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100238}
239
240void Transaction::UndoObjectModifications() {
241 // TODO we may not need to restore objects allocated during this transaction. Or we could directly
242 // remove them from the heap.
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800243 for (const auto& it : object_logs_) {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100244 it.second.Undo(it.first);
245 }
246 object_logs_.clear();
247}
248
249void Transaction::UndoArrayModifications() {
250 // TODO we may not need to restore array allocated during this transaction. Or we could directly
251 // remove them from the heap.
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800252 for (const auto& it : array_logs_) {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100253 it.second.Undo(it.first);
254 }
255 array_logs_.clear();
256}
257
258void Transaction::UndoInternStringTableModifications() {
259 InternTable* const intern_table = Runtime::Current()->GetInternTable();
260 // We want to undo each operation from the most recent to the oldest. List has been filled so the
261 // most recent operation is at list begin so just have to iterate over it.
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800262 for (const InternStringLog& string_log : intern_string_logs_) {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100263 string_log.Undo(intern_table);
264 }
265 intern_string_logs_.clear();
266}
267
Mathieu Chartierbb816d62016-09-07 10:17:46 -0700268void Transaction::UndoResolveStringModifications() {
269 for (ResolveStringLog& string_log : resolve_string_logs_) {
270 string_log.Undo();
271 }
272 resolve_string_logs_.clear();
273}
274
Mathieu Chartierbb87e0f2015-04-03 11:21:55 -0700275void Transaction::VisitRoots(RootVisitor* visitor) {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100276 MutexLock mu(Thread::Current(), log_lock_);
Chang Xingcade5c32017-07-20 17:56:26 -0700277 visitor->VisitRoot(reinterpret_cast<mirror::Object**>(&root_), RootInfo(kRootUnknown));
Mathieu Chartierbb87e0f2015-04-03 11:21:55 -0700278 VisitObjectLogs(visitor);
279 VisitArrayLogs(visitor);
Mathieu Chartierbb816d62016-09-07 10:17:46 -0700280 VisitInternStringLogs(visitor);
281 VisitResolveStringLogs(visitor);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100282}
283
Mathieu Chartierbb87e0f2015-04-03 11:21:55 -0700284void Transaction::VisitObjectLogs(RootVisitor* visitor) {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100285 // List of moving roots.
286 typedef std::pair<mirror::Object*, mirror::Object*> ObjectPair;
287 std::list<ObjectPair> moving_roots;
288
289 // Visit roots.
Mathieu Chartier5f257b12017-02-03 14:47:36 -0800290 for (auto& it : object_logs_) {
Mathieu Chartierbb87e0f2015-04-03 11:21:55 -0700291 it.second.VisitRoots(visitor);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100292 mirror::Object* old_root = it.first;
Mathieu Chartier815873e2014-02-13 18:02:13 -0800293 mirror::Object* new_root = old_root;
Mathieu Chartierbb87e0f2015-04-03 11:21:55 -0700294 visitor->VisitRoot(&new_root, RootInfo(kRootUnknown));
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100295 if (new_root != old_root) {
296 moving_roots.push_back(std::make_pair(old_root, new_root));
297 }
298 }
299
300 // Update object logs with moving roots.
301 for (const ObjectPair& pair : moving_roots) {
302 mirror::Object* old_root = pair.first;
303 mirror::Object* new_root = pair.second;
304 auto old_root_it = object_logs_.find(old_root);
305 CHECK(old_root_it != object_logs_.end());
306 CHECK(object_logs_.find(new_root) == object_logs_.end());
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800307 object_logs_.emplace(new_root, std::move(old_root_it->second));
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100308 object_logs_.erase(old_root_it);
309 }
310}
311
Mathieu Chartierbb87e0f2015-04-03 11:21:55 -0700312void Transaction::VisitArrayLogs(RootVisitor* visitor) {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100313 // List of moving roots.
314 typedef std::pair<mirror::Array*, mirror::Array*> ArrayPair;
315 std::list<ArrayPair> moving_roots;
316
Mathieu Chartier5f257b12017-02-03 14:47:36 -0800317 for (auto& it : array_logs_) {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100318 mirror::Array* old_root = it.first;
Sebastien Hertzee1d79a2014-02-21 15:46:30 +0100319 CHECK(!old_root->IsObjectArray());
Mathieu Chartier815873e2014-02-13 18:02:13 -0800320 mirror::Array* new_root = old_root;
Mathieu Chartierbb87e0f2015-04-03 11:21:55 -0700321 visitor->VisitRoot(reinterpret_cast<mirror::Object**>(&new_root), RootInfo(kRootUnknown));
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100322 if (new_root != old_root) {
323 moving_roots.push_back(std::make_pair(old_root, new_root));
324 }
325 }
326
327 // Update array logs with moving roots.
328 for (const ArrayPair& pair : moving_roots) {
329 mirror::Array* old_root = pair.first;
330 mirror::Array* new_root = pair.second;
331 auto old_root_it = array_logs_.find(old_root);
332 CHECK(old_root_it != array_logs_.end());
333 CHECK(array_logs_.find(new_root) == array_logs_.end());
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800334 array_logs_.emplace(new_root, std::move(old_root_it->second));
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100335 array_logs_.erase(old_root_it);
336 }
337}
338
Mathieu Chartierbb816d62016-09-07 10:17:46 -0700339void Transaction::VisitInternStringLogs(RootVisitor* visitor) {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100340 for (InternStringLog& log : intern_string_logs_) {
Mathieu Chartierbb87e0f2015-04-03 11:21:55 -0700341 log.VisitRoots(visitor);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100342 }
343}
344
Mathieu Chartierbb816d62016-09-07 10:17:46 -0700345void Transaction::VisitResolveStringLogs(RootVisitor* visitor) {
346 for (ResolveStringLog& log : resolve_string_logs_) {
347 log.VisitRoots(visitor);
348 }
349}
350
Fred Shih37f05ef2014-07-16 18:38:08 -0700351void Transaction::ObjectLog::LogBooleanValue(MemberOffset offset, uint8_t value, bool is_volatile) {
352 LogValue(ObjectLog::kBoolean, offset, value, is_volatile);
353}
354
355void Transaction::ObjectLog::LogByteValue(MemberOffset offset, int8_t value, bool is_volatile) {
356 LogValue(ObjectLog::kByte, offset, value, is_volatile);
357}
358
359void Transaction::ObjectLog::LogCharValue(MemberOffset offset, uint16_t value, bool is_volatile) {
360 LogValue(ObjectLog::kChar, offset, value, is_volatile);
361}
362
363void Transaction::ObjectLog::LogShortValue(MemberOffset offset, int16_t value, bool is_volatile) {
364 LogValue(ObjectLog::kShort, offset, value, is_volatile);
365}
366
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100367void Transaction::ObjectLog::Log32BitsValue(MemberOffset offset, uint32_t value, bool is_volatile) {
Fred Shih37f05ef2014-07-16 18:38:08 -0700368 LogValue(ObjectLog::k32Bits, offset, value, is_volatile);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100369}
370
371void Transaction::ObjectLog::Log64BitsValue(MemberOffset offset, uint64_t value, bool is_volatile) {
Fred Shih37f05ef2014-07-16 18:38:08 -0700372 LogValue(ObjectLog::k64Bits, offset, value, is_volatile);
373}
374
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800375void Transaction::ObjectLog::LogReferenceValue(MemberOffset offset,
376 mirror::Object* obj,
377 bool is_volatile) {
Fred Shih37f05ef2014-07-16 18:38:08 -0700378 LogValue(ObjectLog::kReference, offset, reinterpret_cast<uintptr_t>(obj), is_volatile);
379}
380
381void Transaction::ObjectLog::LogValue(ObjectLog::FieldValueKind kind,
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800382 MemberOffset offset,
383 uint64_t value,
384 bool is_volatile) {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100385 auto it = field_values_.find(offset.Uint32Value());
386 if (it == field_values_.end()) {
387 ObjectLog::FieldValue field_value;
388 field_value.value = value;
389 field_value.is_volatile = is_volatile;
Fred Shih37f05ef2014-07-16 18:38:08 -0700390 field_value.kind = kind;
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800391 field_values_.emplace(offset.Uint32Value(), std::move(field_value));
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100392 }
393}
394
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800395void Transaction::ObjectLog::Undo(mirror::Object* obj) const {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100396 for (auto& it : field_values_) {
397 // Garbage collector needs to access object's class and array's length. So we don't rollback
398 // these values.
399 MemberOffset field_offset(it.first);
400 if (field_offset.Uint32Value() == mirror::Class::ClassOffset().Uint32Value()) {
401 // Skip Object::class field.
402 continue;
403 }
404 if (obj->IsArrayInstance() &&
405 field_offset.Uint32Value() == mirror::Array::LengthOffset().Uint32Value()) {
406 // Skip Array::length field.
407 continue;
408 }
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800409 const FieldValue& field_value = it.second;
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100410 UndoFieldWrite(obj, field_offset, field_value);
411 }
412}
413
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800414void Transaction::ObjectLog::UndoFieldWrite(mirror::Object* obj,
415 MemberOffset field_offset,
416 const FieldValue& field_value) const {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100417 // TODO We may want to abort a transaction while still being in transaction mode. In this case,
418 // we'd need to disable the check.
419 constexpr bool kCheckTransaction = true;
420 switch (field_value.kind) {
Fred Shih37f05ef2014-07-16 18:38:08 -0700421 case kBoolean:
422 if (UNLIKELY(field_value.is_volatile)) {
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800423 obj->SetFieldBooleanVolatile<false, kCheckTransaction>(
424 field_offset,
425 static_cast<bool>(field_value.value));
Fred Shih37f05ef2014-07-16 18:38:08 -0700426 } else {
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800427 obj->SetFieldBoolean<false, kCheckTransaction>(
428 field_offset,
429 static_cast<bool>(field_value.value));
Fred Shih37f05ef2014-07-16 18:38:08 -0700430 }
431 break;
432 case kByte:
433 if (UNLIKELY(field_value.is_volatile)) {
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800434 obj->SetFieldByteVolatile<false, kCheckTransaction>(
435 field_offset,
436 static_cast<int8_t>(field_value.value));
Fred Shih37f05ef2014-07-16 18:38:08 -0700437 } else {
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800438 obj->SetFieldByte<false, kCheckTransaction>(
439 field_offset,
440 static_cast<int8_t>(field_value.value));
Fred Shih37f05ef2014-07-16 18:38:08 -0700441 }
442 break;
443 case kChar:
444 if (UNLIKELY(field_value.is_volatile)) {
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800445 obj->SetFieldCharVolatile<false, kCheckTransaction>(
446 field_offset,
447 static_cast<uint16_t>(field_value.value));
Fred Shih37f05ef2014-07-16 18:38:08 -0700448 } else {
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800449 obj->SetFieldChar<false, kCheckTransaction>(
450 field_offset,
451 static_cast<uint16_t>(field_value.value));
Fred Shih37f05ef2014-07-16 18:38:08 -0700452 }
453 break;
454 case kShort:
455 if (UNLIKELY(field_value.is_volatile)) {
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800456 obj->SetFieldShortVolatile<false, kCheckTransaction>(
457 field_offset,
458 static_cast<int16_t>(field_value.value));
Fred Shih37f05ef2014-07-16 18:38:08 -0700459 } else {
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800460 obj->SetFieldShort<false, kCheckTransaction>(
461 field_offset,
462 static_cast<int16_t>(field_value.value));
Fred Shih37f05ef2014-07-16 18:38:08 -0700463 }
464 break;
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100465 case k32Bits:
Ian Rogersb0fa5dc2014-04-28 16:47:08 -0700466 if (UNLIKELY(field_value.is_volatile)) {
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800467 obj->SetField32Volatile<false, kCheckTransaction>(
468 field_offset,
469 static_cast<uint32_t>(field_value.value));
Ian Rogersb0fa5dc2014-04-28 16:47:08 -0700470 } else {
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800471 obj->SetField32<false, kCheckTransaction>(
472 field_offset,
473 static_cast<uint32_t>(field_value.value));
Ian Rogersb0fa5dc2014-04-28 16:47:08 -0700474 }
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100475 break;
476 case k64Bits:
Ian Rogersb0fa5dc2014-04-28 16:47:08 -0700477 if (UNLIKELY(field_value.is_volatile)) {
478 obj->SetField64Volatile<false, kCheckTransaction>(field_offset, field_value.value);
479 } else {
480 obj->SetField64<false, kCheckTransaction>(field_offset, field_value.value);
481 }
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100482 break;
483 case kReference:
Ian Rogersb0fa5dc2014-04-28 16:47:08 -0700484 if (UNLIKELY(field_value.is_volatile)) {
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800485 obj->SetFieldObjectVolatile<false, kCheckTransaction>(
486 field_offset,
487 reinterpret_cast<mirror::Object*>(field_value.value));
Ian Rogersb0fa5dc2014-04-28 16:47:08 -0700488 } else {
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800489 obj->SetFieldObject<false, kCheckTransaction>(
490 field_offset,
491 reinterpret_cast<mirror::Object*>(field_value.value));
Ian Rogersb0fa5dc2014-04-28 16:47:08 -0700492 }
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100493 break;
494 default:
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700495 LOG(FATAL) << "Unknown value kind " << static_cast<int>(field_value.kind);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100496 break;
497 }
498}
499
Mathieu Chartierbb87e0f2015-04-03 11:21:55 -0700500void Transaction::ObjectLog::VisitRoots(RootVisitor* visitor) {
Mathieu Chartier5f257b12017-02-03 14:47:36 -0800501 for (auto& it : field_values_) {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100502 FieldValue& field_value = it.second;
503 if (field_value.kind == ObjectLog::kReference) {
Mathieu Chartierbb87e0f2015-04-03 11:21:55 -0700504 visitor->VisitRootIfNonNull(reinterpret_cast<mirror::Object**>(&field_value.value),
505 RootInfo(kRootUnknown));
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100506 }
507 }
508}
509
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800510void Transaction::InternStringLog::Undo(InternTable* intern_table) const {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100511 DCHECK(intern_table != nullptr);
512 switch (string_op_) {
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700513 case InternStringLog::kInsert: {
514 switch (string_kind_) {
515 case InternStringLog::kStrongString:
Mathieu Chartier9e868092016-10-31 14:58:04 -0700516 intern_table->RemoveStrongFromTransaction(str_.Read());
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700517 break;
518 case InternStringLog::kWeakString:
Mathieu Chartier9e868092016-10-31 14:58:04 -0700519 intern_table->RemoveWeakFromTransaction(str_.Read());
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700520 break;
521 default:
522 LOG(FATAL) << "Unknown interned string kind";
523 break;
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100524 }
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700525 break;
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100526 }
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700527 case InternStringLog::kRemove: {
528 switch (string_kind_) {
529 case InternStringLog::kStrongString:
Mathieu Chartier9e868092016-10-31 14:58:04 -0700530 intern_table->InsertStrongFromTransaction(str_.Read());
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700531 break;
532 case InternStringLog::kWeakString:
Mathieu Chartier9e868092016-10-31 14:58:04 -0700533 intern_table->InsertWeakFromTransaction(str_.Read());
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700534 break;
535 default:
536 LOG(FATAL) << "Unknown interned string kind";
537 break;
538 }
539 break;
540 }
541 default:
542 LOG(FATAL) << "Unknown interned string op";
543 break;
544 }
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100545}
546
Mathieu Chartierbb87e0f2015-04-03 11:21:55 -0700547void Transaction::InternStringLog::VisitRoots(RootVisitor* visitor) {
Mathieu Chartier9e868092016-10-31 14:58:04 -0700548 str_.VisitRoot(visitor, RootInfo(kRootInternedString));
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100549}
550
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800551void Transaction::ResolveStringLog::Undo() const {
Mathieu Chartierbb816d62016-09-07 10:17:46 -0700552 dex_cache_.Read()->ClearString(string_idx_);
553}
554
Mathieu Chartier9e868092016-10-31 14:58:04 -0700555Transaction::ResolveStringLog::ResolveStringLog(ObjPtr<mirror::DexCache> dex_cache,
Andreas Gampe8a0128a2016-11-28 07:38:35 -0800556 dex::StringIndex string_idx)
Mathieu Chartierbb816d62016-09-07 10:17:46 -0700557 : dex_cache_(dex_cache),
558 string_idx_(string_idx) {
559 DCHECK(dex_cache != nullptr);
Andreas Gampe8a0128a2016-11-28 07:38:35 -0800560 DCHECK_LT(string_idx_.index_, dex_cache->GetDexFile()->NumStringIds());
Mathieu Chartierbb816d62016-09-07 10:17:46 -0700561}
562
563void Transaction::ResolveStringLog::VisitRoots(RootVisitor* visitor) {
564 dex_cache_.VisitRoot(visitor, RootInfo(kRootVMInternal));
565}
566
Mathieu Chartier9e868092016-10-31 14:58:04 -0700567Transaction::InternStringLog::InternStringLog(ObjPtr<mirror::String> s,
568 StringKind kind,
569 StringOp op)
570 : str_(s),
571 string_kind_(kind),
572 string_op_(op) {
573 DCHECK(s != nullptr);
574}
575
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100576void Transaction::ArrayLog::LogValue(size_t index, uint64_t value) {
577 auto it = array_values_.find(index);
578 if (it == array_values_.end()) {
579 array_values_.insert(std::make_pair(index, value));
580 }
581}
582
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800583void Transaction::ArrayLog::Undo(mirror::Array* array) const {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100584 DCHECK(array != nullptr);
585 DCHECK(array->IsArrayInstance());
586 Primitive::Type type = array->GetClass()->GetComponentType()->GetPrimitiveType();
587 for (auto it : array_values_) {
588 UndoArrayWrite(array, type, it.first, it.second);
589 }
590}
591
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800592void Transaction::ArrayLog::UndoArrayWrite(mirror::Array* array,
593 Primitive::Type array_type,
594 size_t index,
595 uint64_t value) const {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100596 // TODO We may want to abort a transaction while still being in transaction mode. In this case,
597 // we'd need to disable the check.
598 switch (array_type) {
599 case Primitive::kPrimBoolean:
600 array->AsBooleanArray()->SetWithoutChecks<false>(index, static_cast<uint8_t>(value));
601 break;
602 case Primitive::kPrimByte:
603 array->AsByteArray()->SetWithoutChecks<false>(index, static_cast<int8_t>(value));
604 break;
605 case Primitive::kPrimChar:
606 array->AsCharArray()->SetWithoutChecks<false>(index, static_cast<uint16_t>(value));
607 break;
608 case Primitive::kPrimShort:
609 array->AsShortArray()->SetWithoutChecks<false>(index, static_cast<int16_t>(value));
610 break;
611 case Primitive::kPrimInt:
612 array->AsIntArray()->SetWithoutChecks<false>(index, static_cast<int32_t>(value));
613 break;
614 case Primitive::kPrimFloat:
615 array->AsFloatArray()->SetWithoutChecks<false>(index, static_cast<float>(value));
616 break;
617 case Primitive::kPrimLong:
618 array->AsLongArray()->SetWithoutChecks<false>(index, static_cast<int64_t>(value));
619 break;
620 case Primitive::kPrimDouble:
621 array->AsDoubleArray()->SetWithoutChecks<false>(index, static_cast<double>(value));
622 break;
Sebastien Hertzee1d79a2014-02-21 15:46:30 +0100623 case Primitive::kPrimNot:
624 LOG(FATAL) << "ObjectArray should be treated as Object";
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100625 break;
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100626 default:
627 LOG(FATAL) << "Unsupported type " << array_type;
628 }
629}
630
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100631} // namespace art