blob: 46bbea33e00a7dd1f9d012ab191c994a6d9fcc10 [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
Andreas Gampe57943812017-12-06 21:39:13 -080019#include <android-base/logging.h>
20
Vladimir Marko7ed2d382019-11-25 10:41:53 +000021#include "aot_class_linker.h"
Andreas Gampe88dbad32018-06-26 19:54:12 -070022#include "base/mutex-inl.h"
Andreas Gampe8cf9cb32017-07-19 09:28:38 -070023#include "base/stl_util.h"
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +010024#include "gc/accounting/card_table-inl.h"
Vladimir Marko672c0802019-07-26 13:03:13 +010025#include "gc/heap.h"
Andreas Gampe508fdf32017-06-05 16:42:13 -070026#include "gc_root-inl.h"
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +010027#include "intern_table.h"
Mathieu Chartiere401d142015-04-22 13:56:20 -070028#include "mirror/class-inl.h"
Andreas Gampe508fdf32017-06-05 16:42:13 -070029#include "mirror/dex_cache-inl.h"
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +010030#include "mirror/object-inl.h"
31#include "mirror/object_array-inl.h"
Vladimir Marko672c0802019-07-26 13:03:13 +010032#include "obj_ptr-inl.h"
33#include "runtime.h"
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +010034
35#include <list>
36
37namespace art {
38
39// TODO: remove (only used for debugging purpose).
40static constexpr bool kEnableTransactionStats = false;
41
Vladimir Marko672c0802019-07-26 13:03:13 +010042Transaction::Transaction(bool strict, mirror::Class* root)
43 : log_lock_("transaction log lock", kTransactionLogLock),
44 aborted_(false),
45 rolling_back_(false),
46 heap_(strict ? nullptr : Runtime::Current()->GetHeap()),
47 root_(root) {
48 DCHECK_EQ(strict, IsStrict());
49 DCHECK(Runtime::Current()->IsAotCompiler());
Chang Xingcade5c32017-07-20 17:56:26 -070050}
51
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +010052Transaction::~Transaction() {
53 if (kEnableTransactionStats) {
54 MutexLock mu(Thread::Current(), log_lock_);
55 size_t objects_count = object_logs_.size();
56 size_t field_values_count = 0;
Mathieu Chartier38e954c2017-02-03 16:06:35 -080057 for (const auto& it : object_logs_) {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +010058 field_values_count += it.second.Size();
59 }
60 size_t array_count = array_logs_.size();
61 size_t array_values_count = 0;
Mathieu Chartier38e954c2017-02-03 16:06:35 -080062 for (const auto& it : array_logs_) {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +010063 array_values_count += it.second.Size();
64 }
Mathieu Chartierbb816d62016-09-07 10:17:46 -070065 size_t intern_string_count = intern_string_logs_.size();
66 size_t resolve_string_count = resolve_string_logs_.size();
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +010067 LOG(INFO) << "Transaction::~Transaction"
68 << ": objects_count=" << objects_count
69 << ", field_values_count=" << field_values_count
70 << ", array_count=" << array_count
71 << ", array_values_count=" << array_values_count
Mathieu Chartierbb816d62016-09-07 10:17:46 -070072 << ", intern_string_count=" << intern_string_count
73 << ", resolve_string_count=" << resolve_string_count;
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +010074 }
75}
76
Sebastien Hertz1c80bec2015-02-03 11:58:06 +010077void Transaction::Abort(const std::string& abort_message) {
78 MutexLock mu(Thread::Current(), log_lock_);
Sebastien Hertz2fd7e692015-04-02 11:11:19 +020079 // We may abort more than once if the exception thrown at the time of the
80 // previous abort has been caught during execution of a class initializer.
Sebastien Hertz1c80bec2015-02-03 11:58:06 +010081 // We just keep the message of the first abort because it will cause the
82 // transaction to be rolled back anyway.
83 if (!aborted_) {
84 aborted_ = true;
85 abort_message_ = abort_message;
86 }
87}
88
Sebastien Hertzb81e1cd2015-04-28 12:31:41 +020089void Transaction::ThrowAbortError(Thread* self, const std::string* abort_message) {
90 const bool rethrow = (abort_message == nullptr);
Sebastien Hertzbd9cf9f2015-03-03 12:16:13 +010091 if (kIsDebugBuild && rethrow) {
Sebastien Hertz2fd7e692015-04-02 11:11:19 +020092 CHECK(IsAborted()) << "Rethrow " << Transaction::kAbortExceptionDescriptor
93 << " while transaction is not aborted";
Sebastien Hertzbd9cf9f2015-03-03 12:16:13 +010094 }
Sebastien Hertzb81e1cd2015-04-28 12:31:41 +020095 if (rethrow) {
96 // Rethrow an exception with the earlier abort message stored in the transaction.
97 self->ThrowNewWrappedException(Transaction::kAbortExceptionSignature,
98 GetAbortMessage().c_str());
99 } else {
100 // Throw an exception with the given abort message.
101 self->ThrowNewWrappedException(Transaction::kAbortExceptionSignature,
102 abort_message->c_str());
103 }
Sebastien Hertz1c80bec2015-02-03 11:58:06 +0100104}
105
106bool Transaction::IsAborted() {
107 MutexLock mu(Thread::Current(), log_lock_);
108 return aborted_;
109}
110
Chang Xing605fe242017-07-20 15:57:21 -0700111bool Transaction::IsRollingBack() {
112 return rolling_back_;
113}
114
Sebastien Hertz1c80bec2015-02-03 11:58:06 +0100115const std::string& Transaction::GetAbortMessage() {
116 MutexLock mu(Thread::Current(), log_lock_);
117 return abort_message_;
118}
119
Vladimir Marko672c0802019-07-26 13:03:13 +0100120bool Transaction::WriteConstraint(Thread* self, ObjPtr<mirror::Object> obj, ArtField* field) {
121 MutexLock mu(self, log_lock_);
122 if (IsStrict()) {
123 return field->IsStatic() && // no constraint instance updating
124 obj != root_; // modifying other classes' static field, fail
125 } else {
126 // For boot image extension, prevent changes in boot image.
127 // For boot image there are no boot image spaces and this returns false.
128 return heap_->ObjectIsInBootImageSpace(obj);
Chang Xingbd208d82017-07-12 14:53:17 -0700129 }
Chang Xingbd208d82017-07-12 14:53:17 -0700130}
131
Vladimir Marko149cdda2019-11-12 15:02:51 +0000132bool Transaction::WriteValueConstraint(Thread* self, ObjPtr<mirror::Object> value) {
133 if (value == nullptr) {
134 return false; // We can always store null values.
135 }
136 gc::Heap* heap = Runtime::Current()->GetHeap();
137 MutexLock mu(self, log_lock_);
138 if (IsStrict()) {
139 // TODO: Should we restrict writes the same way as for boot image extension?
140 return false;
141 } else if (heap->GetBootImageSpaces().empty()) {
142 return false; // No constraints for boot image.
143 } else {
144 // Boot image extension.
Vladimir Marko149cdda2019-11-12 15:02:51 +0000145 ObjPtr<mirror::Class> klass = value->IsClass() ? value->AsClass() : value->GetClass();
Vladimir Marko7ed2d382019-11-25 10:41:53 +0000146 return !AotClassLinker::CanReferenceInBootImageExtension(klass, heap);
Vladimir Marko149cdda2019-11-12 15:02:51 +0000147 }
148}
149
Vladimir Marko672c0802019-07-26 13:03:13 +0100150bool Transaction::ReadConstraint(Thread* self, ObjPtr<mirror::Object> obj, ArtField* field) {
Chang Xingbd208d82017-07-12 14:53:17 -0700151 DCHECK(field->IsStatic());
152 DCHECK(obj->IsClass());
Vladimir Marko672c0802019-07-26 13:03:13 +0100153 MutexLock mu(self, log_lock_);
154 if (IsStrict()) {
155 return obj != root_; // fail if not self-updating
156 } else {
157 // For boot image and boot image extension, allow reading any field.
Chang Xingbd208d82017-07-12 14:53:17 -0700158 return false;
159 }
Chang Xingbd208d82017-07-12 14:53:17 -0700160}
161
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800162void Transaction::RecordWriteFieldBoolean(mirror::Object* obj,
163 MemberOffset field_offset,
164 uint8_t value,
165 bool is_volatile) {
Fred Shih37f05ef2014-07-16 18:38:08 -0700166 DCHECK(obj != nullptr);
167 MutexLock mu(Thread::Current(), log_lock_);
168 ObjectLog& object_log = object_logs_[obj];
169 object_log.LogBooleanValue(field_offset, value, is_volatile);
170}
171
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800172void Transaction::RecordWriteFieldByte(mirror::Object* obj,
173 MemberOffset field_offset,
174 int8_t value,
175 bool is_volatile) {
Fred Shih37f05ef2014-07-16 18:38:08 -0700176 DCHECK(obj != nullptr);
177 MutexLock mu(Thread::Current(), log_lock_);
178 ObjectLog& object_log = object_logs_[obj];
179 object_log.LogByteValue(field_offset, value, is_volatile);
180}
181
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800182void Transaction::RecordWriteFieldChar(mirror::Object* obj,
183 MemberOffset field_offset,
184 uint16_t value,
185 bool is_volatile) {
Fred Shih37f05ef2014-07-16 18:38:08 -0700186 DCHECK(obj != nullptr);
187 MutexLock mu(Thread::Current(), log_lock_);
188 ObjectLog& object_log = object_logs_[obj];
189 object_log.LogCharValue(field_offset, value, is_volatile);
190}
191
192
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800193void Transaction::RecordWriteFieldShort(mirror::Object* obj,
194 MemberOffset field_offset,
195 int16_t value,
196 bool is_volatile) {
Fred Shih37f05ef2014-07-16 18:38:08 -0700197 DCHECK(obj != nullptr);
198 MutexLock mu(Thread::Current(), log_lock_);
199 ObjectLog& object_log = object_logs_[obj];
200 object_log.LogShortValue(field_offset, value, is_volatile);
201}
202
203
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800204void Transaction::RecordWriteField32(mirror::Object* obj,
205 MemberOffset field_offset,
206 uint32_t value,
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100207 bool is_volatile) {
208 DCHECK(obj != nullptr);
209 MutexLock mu(Thread::Current(), log_lock_);
210 ObjectLog& object_log = object_logs_[obj];
211 object_log.Log32BitsValue(field_offset, value, is_volatile);
212}
213
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800214void Transaction::RecordWriteField64(mirror::Object* obj,
215 MemberOffset field_offset,
216 uint64_t value,
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100217 bool is_volatile) {
218 DCHECK(obj != nullptr);
219 MutexLock mu(Thread::Current(), log_lock_);
220 ObjectLog& object_log = object_logs_[obj];
221 object_log.Log64BitsValue(field_offset, value, is_volatile);
222}
223
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800224void Transaction::RecordWriteFieldReference(mirror::Object* obj,
225 MemberOffset field_offset,
226 mirror::Object* value,
227 bool is_volatile) {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100228 DCHECK(obj != nullptr);
229 MutexLock mu(Thread::Current(), log_lock_);
230 ObjectLog& object_log = object_logs_[obj];
231 object_log.LogReferenceValue(field_offset, value, is_volatile);
232}
233
234void Transaction::RecordWriteArray(mirror::Array* array, size_t index, uint64_t value) {
235 DCHECK(array != nullptr);
236 DCHECK(array->IsArrayInstance());
Sebastien Hertzee1d79a2014-02-21 15:46:30 +0100237 DCHECK(!array->IsObjectArray());
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100238 MutexLock mu(Thread::Current(), log_lock_);
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800239 auto it = array_logs_.find(array);
240 if (it == array_logs_.end()) {
241 ArrayLog log;
242 it = array_logs_.emplace(array, std::move(log)).first;
243 }
244 it->second.LogValue(index, value);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100245}
246
Andreas Gampe8a0128a2016-11-28 07:38:35 -0800247void Transaction::RecordResolveString(ObjPtr<mirror::DexCache> dex_cache,
248 dex::StringIndex string_idx) {
Mathieu Chartierbb816d62016-09-07 10:17:46 -0700249 DCHECK(dex_cache != nullptr);
Andreas Gampe8a0128a2016-11-28 07:38:35 -0800250 DCHECK_LT(string_idx.index_, dex_cache->GetDexFile()->NumStringIds());
Mathieu Chartierbb816d62016-09-07 10:17:46 -0700251 MutexLock mu(Thread::Current(), log_lock_);
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800252 resolve_string_logs_.emplace_back(dex_cache, string_idx);
Mathieu Chartierbb816d62016-09-07 10:17:46 -0700253}
254
Mathieu Chartier9e868092016-10-31 14:58:04 -0700255void Transaction::RecordStrongStringInsertion(ObjPtr<mirror::String> s) {
Mathieu Chartiercdfd39f2014-08-29 18:16:58 -0700256 InternStringLog log(s, InternStringLog::kStrongString, InternStringLog::kInsert);
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800257 LogInternedString(std::move(log));
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100258}
259
Mathieu Chartier9e868092016-10-31 14:58:04 -0700260void Transaction::RecordWeakStringInsertion(ObjPtr<mirror::String> s) {
Mathieu Chartiercdfd39f2014-08-29 18:16:58 -0700261 InternStringLog log(s, InternStringLog::kWeakString, InternStringLog::kInsert);
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800262 LogInternedString(std::move(log));
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100263}
264
Mathieu Chartier9e868092016-10-31 14:58:04 -0700265void Transaction::RecordStrongStringRemoval(ObjPtr<mirror::String> s) {
Mathieu Chartiercdfd39f2014-08-29 18:16:58 -0700266 InternStringLog log(s, InternStringLog::kStrongString, InternStringLog::kRemove);
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800267 LogInternedString(std::move(log));
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100268}
269
Mathieu Chartier9e868092016-10-31 14:58:04 -0700270void Transaction::RecordWeakStringRemoval(ObjPtr<mirror::String> s) {
Mathieu Chartiercdfd39f2014-08-29 18:16:58 -0700271 InternStringLog log(s, InternStringLog::kWeakString, InternStringLog::kRemove);
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800272 LogInternedString(std::move(log));
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100273}
274
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800275void Transaction::LogInternedString(InternStringLog&& log) {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100276 Locks::intern_table_lock_->AssertExclusiveHeld(Thread::Current());
277 MutexLock mu(Thread::Current(), log_lock_);
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800278 intern_string_logs_.push_front(std::move(log));
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100279}
280
Sebastien Hertz1c80bec2015-02-03 11:58:06 +0100281void Transaction::Rollback() {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100282 Thread* self = Thread::Current();
283 self->AssertNoPendingException();
284 MutexLock mu1(self, *Locks::intern_table_lock_);
285 MutexLock mu2(self, log_lock_);
Chang Xing605fe242017-07-20 15:57:21 -0700286 rolling_back_ = true;
287 CHECK(!Runtime::Current()->IsActiveTransaction());
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100288 UndoObjectModifications();
289 UndoArrayModifications();
290 UndoInternStringTableModifications();
Mathieu Chartierbb816d62016-09-07 10:17:46 -0700291 UndoResolveStringModifications();
Chang Xing605fe242017-07-20 15:57:21 -0700292 rolling_back_ = false;
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100293}
294
295void Transaction::UndoObjectModifications() {
296 // TODO we may not need to restore objects allocated during this transaction. Or we could directly
297 // remove them from the heap.
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800298 for (const auto& it : object_logs_) {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100299 it.second.Undo(it.first);
300 }
301 object_logs_.clear();
302}
303
304void Transaction::UndoArrayModifications() {
305 // TODO we may not need to restore array allocated during this transaction. Or we could directly
306 // remove them from the heap.
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800307 for (const auto& it : array_logs_) {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100308 it.second.Undo(it.first);
309 }
310 array_logs_.clear();
311}
312
313void Transaction::UndoInternStringTableModifications() {
314 InternTable* const intern_table = Runtime::Current()->GetInternTable();
315 // We want to undo each operation from the most recent to the oldest. List has been filled so the
316 // most recent operation is at list begin so just have to iterate over it.
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800317 for (const InternStringLog& string_log : intern_string_logs_) {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100318 string_log.Undo(intern_table);
319 }
320 intern_string_logs_.clear();
321}
322
Mathieu Chartierbb816d62016-09-07 10:17:46 -0700323void Transaction::UndoResolveStringModifications() {
324 for (ResolveStringLog& string_log : resolve_string_logs_) {
325 string_log.Undo();
326 }
327 resolve_string_logs_.clear();
328}
329
Mathieu Chartierbb87e0f2015-04-03 11:21:55 -0700330void Transaction::VisitRoots(RootVisitor* visitor) {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100331 MutexLock mu(Thread::Current(), log_lock_);
Chang Xingcade5c32017-07-20 17:56:26 -0700332 visitor->VisitRoot(reinterpret_cast<mirror::Object**>(&root_), RootInfo(kRootUnknown));
Mathieu Chartierbb87e0f2015-04-03 11:21:55 -0700333 VisitObjectLogs(visitor);
334 VisitArrayLogs(visitor);
Mathieu Chartierbb816d62016-09-07 10:17:46 -0700335 VisitInternStringLogs(visitor);
336 VisitResolveStringLogs(visitor);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100337}
338
Mathieu Chartierbb87e0f2015-04-03 11:21:55 -0700339void Transaction::VisitObjectLogs(RootVisitor* visitor) {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100340 // List of moving roots.
Andreas Gampec55bb392018-09-21 00:02:02 +0000341 using ObjectPair = std::pair<mirror::Object*, mirror::Object*>;
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100342 std::list<ObjectPair> moving_roots;
343
344 // Visit roots.
Mathieu Chartier5f257b12017-02-03 14:47:36 -0800345 for (auto& it : object_logs_) {
Mathieu Chartierbb87e0f2015-04-03 11:21:55 -0700346 it.second.VisitRoots(visitor);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100347 mirror::Object* old_root = it.first;
Mathieu Chartier815873e2014-02-13 18:02:13 -0800348 mirror::Object* new_root = old_root;
Mathieu Chartierbb87e0f2015-04-03 11:21:55 -0700349 visitor->VisitRoot(&new_root, RootInfo(kRootUnknown));
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100350 if (new_root != old_root) {
351 moving_roots.push_back(std::make_pair(old_root, new_root));
352 }
353 }
354
355 // Update object logs with moving roots.
356 for (const ObjectPair& pair : moving_roots) {
357 mirror::Object* old_root = pair.first;
358 mirror::Object* new_root = pair.second;
359 auto old_root_it = object_logs_.find(old_root);
360 CHECK(old_root_it != object_logs_.end());
361 CHECK(object_logs_.find(new_root) == object_logs_.end());
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800362 object_logs_.emplace(new_root, std::move(old_root_it->second));
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100363 object_logs_.erase(old_root_it);
364 }
365}
366
Mathieu Chartierbb87e0f2015-04-03 11:21:55 -0700367void Transaction::VisitArrayLogs(RootVisitor* visitor) {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100368 // List of moving roots.
Andreas Gampec55bb392018-09-21 00:02:02 +0000369 using ArrayPair = std::pair<mirror::Array*, mirror::Array*>;
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100370 std::list<ArrayPair> moving_roots;
371
Mathieu Chartier5f257b12017-02-03 14:47:36 -0800372 for (auto& it : array_logs_) {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100373 mirror::Array* old_root = it.first;
Sebastien Hertzee1d79a2014-02-21 15:46:30 +0100374 CHECK(!old_root->IsObjectArray());
Mathieu Chartier815873e2014-02-13 18:02:13 -0800375 mirror::Array* new_root = old_root;
Mathieu Chartierbb87e0f2015-04-03 11:21:55 -0700376 visitor->VisitRoot(reinterpret_cast<mirror::Object**>(&new_root), RootInfo(kRootUnknown));
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100377 if (new_root != old_root) {
378 moving_roots.push_back(std::make_pair(old_root, new_root));
379 }
380 }
381
382 // Update array logs with moving roots.
383 for (const ArrayPair& pair : moving_roots) {
384 mirror::Array* old_root = pair.first;
385 mirror::Array* new_root = pair.second;
386 auto old_root_it = array_logs_.find(old_root);
387 CHECK(old_root_it != array_logs_.end());
388 CHECK(array_logs_.find(new_root) == array_logs_.end());
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800389 array_logs_.emplace(new_root, std::move(old_root_it->second));
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100390 array_logs_.erase(old_root_it);
391 }
392}
393
Mathieu Chartierbb816d62016-09-07 10:17:46 -0700394void Transaction::VisitInternStringLogs(RootVisitor* visitor) {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100395 for (InternStringLog& log : intern_string_logs_) {
Mathieu Chartierbb87e0f2015-04-03 11:21:55 -0700396 log.VisitRoots(visitor);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100397 }
398}
399
Mathieu Chartierbb816d62016-09-07 10:17:46 -0700400void Transaction::VisitResolveStringLogs(RootVisitor* visitor) {
401 for (ResolveStringLog& log : resolve_string_logs_) {
402 log.VisitRoots(visitor);
403 }
404}
405
Fred Shih37f05ef2014-07-16 18:38:08 -0700406void Transaction::ObjectLog::LogBooleanValue(MemberOffset offset, uint8_t value, bool is_volatile) {
407 LogValue(ObjectLog::kBoolean, offset, value, is_volatile);
408}
409
410void Transaction::ObjectLog::LogByteValue(MemberOffset offset, int8_t value, bool is_volatile) {
411 LogValue(ObjectLog::kByte, offset, value, is_volatile);
412}
413
414void Transaction::ObjectLog::LogCharValue(MemberOffset offset, uint16_t value, bool is_volatile) {
415 LogValue(ObjectLog::kChar, offset, value, is_volatile);
416}
417
418void Transaction::ObjectLog::LogShortValue(MemberOffset offset, int16_t value, bool is_volatile) {
419 LogValue(ObjectLog::kShort, offset, value, is_volatile);
420}
421
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100422void Transaction::ObjectLog::Log32BitsValue(MemberOffset offset, uint32_t value, bool is_volatile) {
Fred Shih37f05ef2014-07-16 18:38:08 -0700423 LogValue(ObjectLog::k32Bits, offset, value, is_volatile);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100424}
425
426void Transaction::ObjectLog::Log64BitsValue(MemberOffset offset, uint64_t value, bool is_volatile) {
Fred Shih37f05ef2014-07-16 18:38:08 -0700427 LogValue(ObjectLog::k64Bits, offset, value, is_volatile);
428}
429
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800430void Transaction::ObjectLog::LogReferenceValue(MemberOffset offset,
431 mirror::Object* obj,
432 bool is_volatile) {
Fred Shih37f05ef2014-07-16 18:38:08 -0700433 LogValue(ObjectLog::kReference, offset, reinterpret_cast<uintptr_t>(obj), is_volatile);
434}
435
436void Transaction::ObjectLog::LogValue(ObjectLog::FieldValueKind kind,
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800437 MemberOffset offset,
438 uint64_t value,
439 bool is_volatile) {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100440 auto it = field_values_.find(offset.Uint32Value());
441 if (it == field_values_.end()) {
442 ObjectLog::FieldValue field_value;
443 field_value.value = value;
444 field_value.is_volatile = is_volatile;
Fred Shih37f05ef2014-07-16 18:38:08 -0700445 field_value.kind = kind;
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800446 field_values_.emplace(offset.Uint32Value(), std::move(field_value));
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100447 }
448}
449
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800450void Transaction::ObjectLog::Undo(mirror::Object* obj) const {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100451 for (auto& it : field_values_) {
452 // Garbage collector needs to access object's class and array's length. So we don't rollback
453 // these values.
454 MemberOffset field_offset(it.first);
455 if (field_offset.Uint32Value() == mirror::Class::ClassOffset().Uint32Value()) {
456 // Skip Object::class field.
457 continue;
458 }
459 if (obj->IsArrayInstance() &&
460 field_offset.Uint32Value() == mirror::Array::LengthOffset().Uint32Value()) {
461 // Skip Array::length field.
462 continue;
463 }
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800464 const FieldValue& field_value = it.second;
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100465 UndoFieldWrite(obj, field_offset, field_value);
466 }
467}
468
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800469void Transaction::ObjectLog::UndoFieldWrite(mirror::Object* obj,
470 MemberOffset field_offset,
471 const FieldValue& field_value) const {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100472 // TODO We may want to abort a transaction while still being in transaction mode. In this case,
473 // we'd need to disable the check.
Chang Xing605fe242017-07-20 15:57:21 -0700474 constexpr bool kCheckTransaction = false;
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100475 switch (field_value.kind) {
Fred Shih37f05ef2014-07-16 18:38:08 -0700476 case kBoolean:
477 if (UNLIKELY(field_value.is_volatile)) {
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800478 obj->SetFieldBooleanVolatile<false, kCheckTransaction>(
479 field_offset,
Andreas Gampe7c5acbb2018-09-20 13:54:52 -0700480 field_value.value);
Fred Shih37f05ef2014-07-16 18:38:08 -0700481 } else {
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800482 obj->SetFieldBoolean<false, kCheckTransaction>(
483 field_offset,
Andreas Gampe7c5acbb2018-09-20 13:54:52 -0700484 field_value.value);
Fred Shih37f05ef2014-07-16 18:38:08 -0700485 }
486 break;
487 case kByte:
488 if (UNLIKELY(field_value.is_volatile)) {
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800489 obj->SetFieldByteVolatile<false, kCheckTransaction>(
490 field_offset,
491 static_cast<int8_t>(field_value.value));
Fred Shih37f05ef2014-07-16 18:38:08 -0700492 } else {
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800493 obj->SetFieldByte<false, kCheckTransaction>(
494 field_offset,
495 static_cast<int8_t>(field_value.value));
Fred Shih37f05ef2014-07-16 18:38:08 -0700496 }
497 break;
498 case kChar:
499 if (UNLIKELY(field_value.is_volatile)) {
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800500 obj->SetFieldCharVolatile<false, kCheckTransaction>(
501 field_offset,
502 static_cast<uint16_t>(field_value.value));
Fred Shih37f05ef2014-07-16 18:38:08 -0700503 } else {
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800504 obj->SetFieldChar<false, kCheckTransaction>(
505 field_offset,
506 static_cast<uint16_t>(field_value.value));
Fred Shih37f05ef2014-07-16 18:38:08 -0700507 }
508 break;
509 case kShort:
510 if (UNLIKELY(field_value.is_volatile)) {
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800511 obj->SetFieldShortVolatile<false, kCheckTransaction>(
512 field_offset,
513 static_cast<int16_t>(field_value.value));
Fred Shih37f05ef2014-07-16 18:38:08 -0700514 } else {
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800515 obj->SetFieldShort<false, kCheckTransaction>(
516 field_offset,
517 static_cast<int16_t>(field_value.value));
Fred Shih37f05ef2014-07-16 18:38:08 -0700518 }
519 break;
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100520 case k32Bits:
Ian Rogersb0fa5dc2014-04-28 16:47:08 -0700521 if (UNLIKELY(field_value.is_volatile)) {
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800522 obj->SetField32Volatile<false, kCheckTransaction>(
523 field_offset,
524 static_cast<uint32_t>(field_value.value));
Ian Rogersb0fa5dc2014-04-28 16:47:08 -0700525 } else {
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800526 obj->SetField32<false, kCheckTransaction>(
527 field_offset,
528 static_cast<uint32_t>(field_value.value));
Ian Rogersb0fa5dc2014-04-28 16:47:08 -0700529 }
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100530 break;
531 case k64Bits:
Ian Rogersb0fa5dc2014-04-28 16:47:08 -0700532 if (UNLIKELY(field_value.is_volatile)) {
533 obj->SetField64Volatile<false, kCheckTransaction>(field_offset, field_value.value);
534 } else {
535 obj->SetField64<false, kCheckTransaction>(field_offset, field_value.value);
536 }
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100537 break;
538 case kReference:
Ian Rogersb0fa5dc2014-04-28 16:47:08 -0700539 if (UNLIKELY(field_value.is_volatile)) {
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800540 obj->SetFieldObjectVolatile<false, kCheckTransaction>(
541 field_offset,
542 reinterpret_cast<mirror::Object*>(field_value.value));
Ian Rogersb0fa5dc2014-04-28 16:47:08 -0700543 } else {
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800544 obj->SetFieldObject<false, kCheckTransaction>(
545 field_offset,
546 reinterpret_cast<mirror::Object*>(field_value.value));
Ian Rogersb0fa5dc2014-04-28 16:47:08 -0700547 }
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100548 break;
549 default:
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700550 LOG(FATAL) << "Unknown value kind " << static_cast<int>(field_value.kind);
Elliott Hughesc1896c92018-11-29 11:33:18 -0800551 UNREACHABLE();
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100552 }
553}
554
Mathieu Chartierbb87e0f2015-04-03 11:21:55 -0700555void Transaction::ObjectLog::VisitRoots(RootVisitor* visitor) {
Mathieu Chartier5f257b12017-02-03 14:47:36 -0800556 for (auto& it : field_values_) {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100557 FieldValue& field_value = it.second;
558 if (field_value.kind == ObjectLog::kReference) {
Mathieu Chartierbb87e0f2015-04-03 11:21:55 -0700559 visitor->VisitRootIfNonNull(reinterpret_cast<mirror::Object**>(&field_value.value),
560 RootInfo(kRootUnknown));
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100561 }
562 }
563}
564
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800565void Transaction::InternStringLog::Undo(InternTable* intern_table) const {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100566 DCHECK(intern_table != nullptr);
567 switch (string_op_) {
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700568 case InternStringLog::kInsert: {
569 switch (string_kind_) {
570 case InternStringLog::kStrongString:
Mathieu Chartier9e868092016-10-31 14:58:04 -0700571 intern_table->RemoveStrongFromTransaction(str_.Read());
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700572 break;
573 case InternStringLog::kWeakString:
Mathieu Chartier9e868092016-10-31 14:58:04 -0700574 intern_table->RemoveWeakFromTransaction(str_.Read());
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700575 break;
576 default:
577 LOG(FATAL) << "Unknown interned string kind";
Elliott Hughesc1896c92018-11-29 11:33:18 -0800578 UNREACHABLE();
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100579 }
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700580 break;
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100581 }
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700582 case InternStringLog::kRemove: {
583 switch (string_kind_) {
584 case InternStringLog::kStrongString:
Mathieu Chartier9e868092016-10-31 14:58:04 -0700585 intern_table->InsertStrongFromTransaction(str_.Read());
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700586 break;
587 case InternStringLog::kWeakString:
Mathieu Chartier9e868092016-10-31 14:58:04 -0700588 intern_table->InsertWeakFromTransaction(str_.Read());
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700589 break;
590 default:
591 LOG(FATAL) << "Unknown interned string kind";
Elliott Hughesc1896c92018-11-29 11:33:18 -0800592 UNREACHABLE();
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700593 }
594 break;
595 }
596 default:
597 LOG(FATAL) << "Unknown interned string op";
Elliott Hughesc1896c92018-11-29 11:33:18 -0800598 UNREACHABLE();
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700599 }
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100600}
601
Mathieu Chartierbb87e0f2015-04-03 11:21:55 -0700602void Transaction::InternStringLog::VisitRoots(RootVisitor* visitor) {
Mathieu Chartier9e868092016-10-31 14:58:04 -0700603 str_.VisitRoot(visitor, RootInfo(kRootInternedString));
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100604}
605
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800606void Transaction::ResolveStringLog::Undo() const {
Mathieu Chartierbb816d62016-09-07 10:17:46 -0700607 dex_cache_.Read()->ClearString(string_idx_);
608}
609
Mathieu Chartier9e868092016-10-31 14:58:04 -0700610Transaction::ResolveStringLog::ResolveStringLog(ObjPtr<mirror::DexCache> dex_cache,
Andreas Gampe8a0128a2016-11-28 07:38:35 -0800611 dex::StringIndex string_idx)
Mathieu Chartierbb816d62016-09-07 10:17:46 -0700612 : dex_cache_(dex_cache),
613 string_idx_(string_idx) {
614 DCHECK(dex_cache != nullptr);
Andreas Gampe8a0128a2016-11-28 07:38:35 -0800615 DCHECK_LT(string_idx_.index_, dex_cache->GetDexFile()->NumStringIds());
Mathieu Chartierbb816d62016-09-07 10:17:46 -0700616}
617
618void Transaction::ResolveStringLog::VisitRoots(RootVisitor* visitor) {
619 dex_cache_.VisitRoot(visitor, RootInfo(kRootVMInternal));
620}
621
Mathieu Chartier9e868092016-10-31 14:58:04 -0700622Transaction::InternStringLog::InternStringLog(ObjPtr<mirror::String> s,
623 StringKind kind,
624 StringOp op)
625 : str_(s),
626 string_kind_(kind),
627 string_op_(op) {
628 DCHECK(s != nullptr);
629}
630
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100631void Transaction::ArrayLog::LogValue(size_t index, uint64_t value) {
632 auto it = array_values_.find(index);
633 if (it == array_values_.end()) {
634 array_values_.insert(std::make_pair(index, value));
635 }
636}
637
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800638void Transaction::ArrayLog::Undo(mirror::Array* array) const {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100639 DCHECK(array != nullptr);
640 DCHECK(array->IsArrayInstance());
641 Primitive::Type type = array->GetClass()->GetComponentType()->GetPrimitiveType();
642 for (auto it : array_values_) {
643 UndoArrayWrite(array, type, it.first, it.second);
644 }
645}
646
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800647void Transaction::ArrayLog::UndoArrayWrite(mirror::Array* array,
648 Primitive::Type array_type,
649 size_t index,
650 uint64_t value) const {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100651 // TODO We may want to abort a transaction while still being in transaction mode. In this case,
652 // we'd need to disable the check.
Chang Xing605fe242017-07-20 15:57:21 -0700653 constexpr bool kCheckTransaction = false;
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100654 switch (array_type) {
655 case Primitive::kPrimBoolean:
Chang Xing605fe242017-07-20 15:57:21 -0700656 array->AsBooleanArray()->SetWithoutChecks<false, kCheckTransaction>(
657 index, static_cast<uint8_t>(value));
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100658 break;
659 case Primitive::kPrimByte:
Chang Xing605fe242017-07-20 15:57:21 -0700660 array->AsByteArray()->SetWithoutChecks<false, kCheckTransaction>(
661 index, static_cast<int8_t>(value));
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100662 break;
663 case Primitive::kPrimChar:
Chang Xing605fe242017-07-20 15:57:21 -0700664 array->AsCharArray()->SetWithoutChecks<false, kCheckTransaction>(
665 index, static_cast<uint16_t>(value));
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100666 break;
667 case Primitive::kPrimShort:
Chang Xing605fe242017-07-20 15:57:21 -0700668 array->AsShortArray()->SetWithoutChecks<false, kCheckTransaction>(
669 index, static_cast<int16_t>(value));
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100670 break;
671 case Primitive::kPrimInt:
Chang Xing605fe242017-07-20 15:57:21 -0700672 array->AsIntArray()->SetWithoutChecks<false, kCheckTransaction>(
673 index, static_cast<int32_t>(value));
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100674 break;
675 case Primitive::kPrimFloat:
Chang Xing605fe242017-07-20 15:57:21 -0700676 array->AsFloatArray()->SetWithoutChecks<false, kCheckTransaction>(
677 index, static_cast<float>(value));
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100678 break;
679 case Primitive::kPrimLong:
Chang Xing605fe242017-07-20 15:57:21 -0700680 array->AsLongArray()->SetWithoutChecks<false, kCheckTransaction>(
681 index, static_cast<int64_t>(value));
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100682 break;
683 case Primitive::kPrimDouble:
Chang Xing605fe242017-07-20 15:57:21 -0700684 array->AsDoubleArray()->SetWithoutChecks<false, kCheckTransaction>(
685 index, static_cast<double>(value));
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100686 break;
Sebastien Hertzee1d79a2014-02-21 15:46:30 +0100687 case Primitive::kPrimNot:
688 LOG(FATAL) << "ObjectArray should be treated as Object";
Elliott Hughesc1896c92018-11-29 11:33:18 -0800689 UNREACHABLE();
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100690 default:
691 LOG(FATAL) << "Unsupported type " << array_type;
Elliott Hughesc1896c92018-11-29 11:33:18 -0800692 UNREACHABLE();
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100693 }
694}
695
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100696} // namespace art