blob: 5d9456bbacc9847c7f06828e0ddf266ed58cf54b [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),
Vladimir Marko4d7b6892020-01-16 17:06:35 +000046 heap_(Runtime::Current()->GetHeap()),
47 strict_(strict),
Vladimir Markob68bb7a2020-03-17 10:55:25 +000048 root_(root),
49 assert_no_new_records_reason_(nullptr) {
Vladimir Marko672c0802019-07-26 13:03:13 +010050 DCHECK(Runtime::Current()->IsAotCompiler());
Chang Xingcade5c32017-07-20 17:56:26 -070051}
52
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +010053Transaction::~Transaction() {
54 if (kEnableTransactionStats) {
55 MutexLock mu(Thread::Current(), log_lock_);
56 size_t objects_count = object_logs_.size();
57 size_t field_values_count = 0;
Mathieu Chartier38e954c2017-02-03 16:06:35 -080058 for (const auto& it : object_logs_) {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +010059 field_values_count += it.second.Size();
60 }
61 size_t array_count = array_logs_.size();
62 size_t array_values_count = 0;
Mathieu Chartier38e954c2017-02-03 16:06:35 -080063 for (const auto& it : array_logs_) {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +010064 array_values_count += it.second.Size();
65 }
Mathieu Chartierbb816d62016-09-07 10:17:46 -070066 size_t intern_string_count = intern_string_logs_.size();
67 size_t resolve_string_count = resolve_string_logs_.size();
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +010068 LOG(INFO) << "Transaction::~Transaction"
69 << ": objects_count=" << objects_count
70 << ", field_values_count=" << field_values_count
71 << ", array_count=" << array_count
72 << ", array_values_count=" << array_values_count
Mathieu Chartierbb816d62016-09-07 10:17:46 -070073 << ", intern_string_count=" << intern_string_count
74 << ", resolve_string_count=" << resolve_string_count;
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +010075 }
76}
77
Sebastien Hertz1c80bec2015-02-03 11:58:06 +010078void Transaction::Abort(const std::string& abort_message) {
79 MutexLock mu(Thread::Current(), log_lock_);
Sebastien Hertz2fd7e692015-04-02 11:11:19 +020080 // We may abort more than once if the exception thrown at the time of the
81 // previous abort has been caught during execution of a class initializer.
Sebastien Hertz1c80bec2015-02-03 11:58:06 +010082 // We just keep the message of the first abort because it will cause the
83 // transaction to be rolled back anyway.
84 if (!aborted_) {
85 aborted_ = true;
86 abort_message_ = abort_message;
87 }
88}
89
Sebastien Hertzb81e1cd2015-04-28 12:31:41 +020090void Transaction::ThrowAbortError(Thread* self, const std::string* abort_message) {
91 const bool rethrow = (abort_message == nullptr);
Sebastien Hertzbd9cf9f2015-03-03 12:16:13 +010092 if (kIsDebugBuild && rethrow) {
Sebastien Hertz2fd7e692015-04-02 11:11:19 +020093 CHECK(IsAborted()) << "Rethrow " << Transaction::kAbortExceptionDescriptor
94 << " while transaction is not aborted";
Sebastien Hertzbd9cf9f2015-03-03 12:16:13 +010095 }
Sebastien Hertzb81e1cd2015-04-28 12:31:41 +020096 if (rethrow) {
97 // Rethrow an exception with the earlier abort message stored in the transaction.
98 self->ThrowNewWrappedException(Transaction::kAbortExceptionSignature,
99 GetAbortMessage().c_str());
100 } else {
101 // Throw an exception with the given abort message.
102 self->ThrowNewWrappedException(Transaction::kAbortExceptionSignature,
103 abort_message->c_str());
104 }
Sebastien Hertz1c80bec2015-02-03 11:58:06 +0100105}
106
107bool Transaction::IsAborted() {
108 MutexLock mu(Thread::Current(), log_lock_);
109 return aborted_;
110}
111
Chang Xing605fe242017-07-20 15:57:21 -0700112bool Transaction::IsRollingBack() {
113 return rolling_back_;
114}
115
Sebastien Hertz1c80bec2015-02-03 11:58:06 +0100116const std::string& Transaction::GetAbortMessage() {
117 MutexLock mu(Thread::Current(), log_lock_);
118 return abort_message_;
119}
120
Vladimir Marko4d7b6892020-01-16 17:06:35 +0000121bool Transaction::WriteConstraint(Thread* self, ObjPtr<mirror::Object> obj) {
122 DCHECK(obj != nullptr);
Vladimir Marko672c0802019-07-26 13:03:13 +0100123 MutexLock mu(self, log_lock_);
Vladimir Marko4d7b6892020-01-16 17:06:35 +0000124
125 // Prevent changes in boot image spaces for app or boot image extension.
126 // For boot image there are no boot image spaces and this condition evaluates to false.
127 if (heap_->ObjectIsInBootImageSpace(obj)) {
128 return true;
Chang Xingbd208d82017-07-12 14:53:17 -0700129 }
Vladimir Marko4d7b6892020-01-16 17:06:35 +0000130
131 // For apps, also prevent writing to other classes.
132 return IsStrict() &&
133 obj->IsClass() && // no constraint updating instances or arrays
134 obj != root_; // modifying other classes' static field, fail
Chang Xingbd208d82017-07-12 14:53:17 -0700135}
136
Vladimir Marko149cdda2019-11-12 15:02:51 +0000137bool Transaction::WriteValueConstraint(Thread* self, ObjPtr<mirror::Object> value) {
138 if (value == nullptr) {
139 return false; // We can always store null values.
140 }
141 gc::Heap* heap = Runtime::Current()->GetHeap();
142 MutexLock mu(self, log_lock_);
143 if (IsStrict()) {
144 // TODO: Should we restrict writes the same way as for boot image extension?
145 return false;
146 } else if (heap->GetBootImageSpaces().empty()) {
147 return false; // No constraints for boot image.
148 } else {
149 // Boot image extension.
Vladimir Marko149cdda2019-11-12 15:02:51 +0000150 ObjPtr<mirror::Class> klass = value->IsClass() ? value->AsClass() : value->GetClass();
Vladimir Marko7ed2d382019-11-25 10:41:53 +0000151 return !AotClassLinker::CanReferenceInBootImageExtension(klass, heap);
Vladimir Marko149cdda2019-11-12 15:02:51 +0000152 }
153}
154
Vladimir Marko4d7b6892020-01-16 17:06:35 +0000155bool Transaction::ReadConstraint(Thread* self, ObjPtr<mirror::Object> obj) {
156 // Read constraints are checked only for static field reads as there are
157 // no constraints on reading instance fields and array elements.
Chang Xingbd208d82017-07-12 14:53:17 -0700158 DCHECK(obj->IsClass());
Vladimir Marko672c0802019-07-26 13:03:13 +0100159 MutexLock mu(self, log_lock_);
160 if (IsStrict()) {
161 return obj != root_; // fail if not self-updating
162 } else {
163 // For boot image and boot image extension, allow reading any field.
Chang Xingbd208d82017-07-12 14:53:17 -0700164 return false;
165 }
Chang Xingbd208d82017-07-12 14:53:17 -0700166}
167
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800168void Transaction::RecordWriteFieldBoolean(mirror::Object* obj,
169 MemberOffset field_offset,
170 uint8_t value,
171 bool is_volatile) {
Fred Shih37f05ef2014-07-16 18:38:08 -0700172 DCHECK(obj != nullptr);
173 MutexLock mu(Thread::Current(), log_lock_);
Vladimir Markob68bb7a2020-03-17 10:55:25 +0000174 DCHECK(assert_no_new_records_reason_ == nullptr) << assert_no_new_records_reason_;
Fred Shih37f05ef2014-07-16 18:38:08 -0700175 ObjectLog& object_log = object_logs_[obj];
176 object_log.LogBooleanValue(field_offset, value, is_volatile);
177}
178
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800179void Transaction::RecordWriteFieldByte(mirror::Object* obj,
180 MemberOffset field_offset,
181 int8_t value,
182 bool is_volatile) {
Fred Shih37f05ef2014-07-16 18:38:08 -0700183 DCHECK(obj != nullptr);
184 MutexLock mu(Thread::Current(), log_lock_);
Vladimir Markob68bb7a2020-03-17 10:55:25 +0000185 DCHECK(assert_no_new_records_reason_ == nullptr) << assert_no_new_records_reason_;
Fred Shih37f05ef2014-07-16 18:38:08 -0700186 ObjectLog& object_log = object_logs_[obj];
187 object_log.LogByteValue(field_offset, value, is_volatile);
188}
189
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800190void Transaction::RecordWriteFieldChar(mirror::Object* obj,
191 MemberOffset field_offset,
192 uint16_t value,
193 bool is_volatile) {
Fred Shih37f05ef2014-07-16 18:38:08 -0700194 DCHECK(obj != nullptr);
195 MutexLock mu(Thread::Current(), log_lock_);
Vladimir Markob68bb7a2020-03-17 10:55:25 +0000196 DCHECK(assert_no_new_records_reason_ == nullptr) << assert_no_new_records_reason_;
Fred Shih37f05ef2014-07-16 18:38:08 -0700197 ObjectLog& object_log = object_logs_[obj];
198 object_log.LogCharValue(field_offset, value, is_volatile);
199}
200
201
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800202void Transaction::RecordWriteFieldShort(mirror::Object* obj,
203 MemberOffset field_offset,
204 int16_t value,
205 bool is_volatile) {
Fred Shih37f05ef2014-07-16 18:38:08 -0700206 DCHECK(obj != nullptr);
207 MutexLock mu(Thread::Current(), log_lock_);
Vladimir Markob68bb7a2020-03-17 10:55:25 +0000208 DCHECK(assert_no_new_records_reason_ == nullptr) << assert_no_new_records_reason_;
Fred Shih37f05ef2014-07-16 18:38:08 -0700209 ObjectLog& object_log = object_logs_[obj];
210 object_log.LogShortValue(field_offset, value, is_volatile);
211}
212
213
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800214void Transaction::RecordWriteField32(mirror::Object* obj,
215 MemberOffset field_offset,
216 uint32_t value,
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100217 bool is_volatile) {
218 DCHECK(obj != nullptr);
219 MutexLock mu(Thread::Current(), log_lock_);
Vladimir Markob68bb7a2020-03-17 10:55:25 +0000220 DCHECK(assert_no_new_records_reason_ == nullptr) << assert_no_new_records_reason_;
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100221 ObjectLog& object_log = object_logs_[obj];
222 object_log.Log32BitsValue(field_offset, value, is_volatile);
223}
224
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800225void Transaction::RecordWriteField64(mirror::Object* obj,
226 MemberOffset field_offset,
227 uint64_t value,
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100228 bool is_volatile) {
229 DCHECK(obj != nullptr);
230 MutexLock mu(Thread::Current(), log_lock_);
Vladimir Markob68bb7a2020-03-17 10:55:25 +0000231 DCHECK(assert_no_new_records_reason_ == nullptr) << assert_no_new_records_reason_;
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100232 ObjectLog& object_log = object_logs_[obj];
233 object_log.Log64BitsValue(field_offset, value, is_volatile);
234}
235
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800236void Transaction::RecordWriteFieldReference(mirror::Object* obj,
237 MemberOffset field_offset,
238 mirror::Object* value,
239 bool is_volatile) {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100240 DCHECK(obj != nullptr);
241 MutexLock mu(Thread::Current(), log_lock_);
Vladimir Markob68bb7a2020-03-17 10:55:25 +0000242 DCHECK(assert_no_new_records_reason_ == nullptr) << assert_no_new_records_reason_;
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100243 ObjectLog& object_log = object_logs_[obj];
244 object_log.LogReferenceValue(field_offset, value, is_volatile);
245}
246
247void Transaction::RecordWriteArray(mirror::Array* array, size_t index, uint64_t value) {
248 DCHECK(array != nullptr);
249 DCHECK(array->IsArrayInstance());
Sebastien Hertzee1d79a2014-02-21 15:46:30 +0100250 DCHECK(!array->IsObjectArray());
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100251 MutexLock mu(Thread::Current(), log_lock_);
Vladimir Markob68bb7a2020-03-17 10:55:25 +0000252 DCHECK(assert_no_new_records_reason_ == nullptr) << assert_no_new_records_reason_;
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800253 auto it = array_logs_.find(array);
254 if (it == array_logs_.end()) {
255 ArrayLog log;
256 it = array_logs_.emplace(array, std::move(log)).first;
257 }
258 it->second.LogValue(index, value);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100259}
260
Andreas Gampe8a0128a2016-11-28 07:38:35 -0800261void Transaction::RecordResolveString(ObjPtr<mirror::DexCache> dex_cache,
262 dex::StringIndex string_idx) {
Mathieu Chartierbb816d62016-09-07 10:17:46 -0700263 DCHECK(dex_cache != nullptr);
Andreas Gampe8a0128a2016-11-28 07:38:35 -0800264 DCHECK_LT(string_idx.index_, dex_cache->GetDexFile()->NumStringIds());
Mathieu Chartierbb816d62016-09-07 10:17:46 -0700265 MutexLock mu(Thread::Current(), log_lock_);
Vladimir Markob68bb7a2020-03-17 10:55:25 +0000266 DCHECK(assert_no_new_records_reason_ == nullptr) << assert_no_new_records_reason_;
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800267 resolve_string_logs_.emplace_back(dex_cache, string_idx);
Mathieu Chartierbb816d62016-09-07 10:17:46 -0700268}
269
Mathieu Chartier9e868092016-10-31 14:58:04 -0700270void Transaction::RecordStrongStringInsertion(ObjPtr<mirror::String> s) {
Mathieu Chartiercdfd39f2014-08-29 18:16:58 -0700271 InternStringLog log(s, InternStringLog::kStrongString, InternStringLog::kInsert);
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800272 LogInternedString(std::move(log));
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100273}
274
Mathieu Chartier9e868092016-10-31 14:58:04 -0700275void Transaction::RecordWeakStringInsertion(ObjPtr<mirror::String> s) {
Mathieu Chartiercdfd39f2014-08-29 18:16:58 -0700276 InternStringLog log(s, InternStringLog::kWeakString, InternStringLog::kInsert);
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800277 LogInternedString(std::move(log));
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100278}
279
Mathieu Chartier9e868092016-10-31 14:58:04 -0700280void Transaction::RecordStrongStringRemoval(ObjPtr<mirror::String> s) {
Mathieu Chartiercdfd39f2014-08-29 18:16:58 -0700281 InternStringLog log(s, InternStringLog::kStrongString, InternStringLog::kRemove);
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800282 LogInternedString(std::move(log));
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100283}
284
Mathieu Chartier9e868092016-10-31 14:58:04 -0700285void Transaction::RecordWeakStringRemoval(ObjPtr<mirror::String> s) {
Mathieu Chartiercdfd39f2014-08-29 18:16:58 -0700286 InternStringLog log(s, InternStringLog::kWeakString, InternStringLog::kRemove);
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800287 LogInternedString(std::move(log));
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100288}
289
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800290void Transaction::LogInternedString(InternStringLog&& log) {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100291 Locks::intern_table_lock_->AssertExclusiveHeld(Thread::Current());
292 MutexLock mu(Thread::Current(), log_lock_);
Vladimir Markob68bb7a2020-03-17 10:55:25 +0000293 DCHECK(assert_no_new_records_reason_ == nullptr) << assert_no_new_records_reason_;
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800294 intern_string_logs_.push_front(std::move(log));
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100295}
296
Sebastien Hertz1c80bec2015-02-03 11:58:06 +0100297void Transaction::Rollback() {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100298 Thread* self = Thread::Current();
299 self->AssertNoPendingException();
300 MutexLock mu1(self, *Locks::intern_table_lock_);
301 MutexLock mu2(self, log_lock_);
Chang Xing605fe242017-07-20 15:57:21 -0700302 rolling_back_ = true;
303 CHECK(!Runtime::Current()->IsActiveTransaction());
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100304 UndoObjectModifications();
305 UndoArrayModifications();
306 UndoInternStringTableModifications();
Mathieu Chartierbb816d62016-09-07 10:17:46 -0700307 UndoResolveStringModifications();
Chang Xing605fe242017-07-20 15:57:21 -0700308 rolling_back_ = false;
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100309}
310
311void Transaction::UndoObjectModifications() {
312 // TODO we may not need to restore objects allocated during this transaction. Or we could directly
313 // remove them from the heap.
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800314 for (const auto& it : object_logs_) {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100315 it.second.Undo(it.first);
316 }
317 object_logs_.clear();
318}
319
320void Transaction::UndoArrayModifications() {
321 // TODO we may not need to restore array allocated during this transaction. Or we could directly
322 // remove them from the heap.
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800323 for (const auto& it : array_logs_) {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100324 it.second.Undo(it.first);
325 }
326 array_logs_.clear();
327}
328
329void Transaction::UndoInternStringTableModifications() {
330 InternTable* const intern_table = Runtime::Current()->GetInternTable();
331 // We want to undo each operation from the most recent to the oldest. List has been filled so the
332 // most recent operation is at list begin so just have to iterate over it.
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800333 for (const InternStringLog& string_log : intern_string_logs_) {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100334 string_log.Undo(intern_table);
335 }
336 intern_string_logs_.clear();
337}
338
Mathieu Chartierbb816d62016-09-07 10:17:46 -0700339void Transaction::UndoResolveStringModifications() {
340 for (ResolveStringLog& string_log : resolve_string_logs_) {
341 string_log.Undo();
342 }
343 resolve_string_logs_.clear();
344}
345
Mathieu Chartierbb87e0f2015-04-03 11:21:55 -0700346void Transaction::VisitRoots(RootVisitor* visitor) {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100347 MutexLock mu(Thread::Current(), log_lock_);
Chang Xingcade5c32017-07-20 17:56:26 -0700348 visitor->VisitRoot(reinterpret_cast<mirror::Object**>(&root_), RootInfo(kRootUnknown));
Mathieu Chartierbb87e0f2015-04-03 11:21:55 -0700349 VisitObjectLogs(visitor);
350 VisitArrayLogs(visitor);
Mathieu Chartierbb816d62016-09-07 10:17:46 -0700351 VisitInternStringLogs(visitor);
352 VisitResolveStringLogs(visitor);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100353}
354
Mathieu Chartierbb87e0f2015-04-03 11:21:55 -0700355void Transaction::VisitObjectLogs(RootVisitor* visitor) {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100356 // List of moving roots.
Andreas Gampec55bb392018-09-21 00:02:02 +0000357 using ObjectPair = std::pair<mirror::Object*, mirror::Object*>;
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100358 std::list<ObjectPair> moving_roots;
359
360 // Visit roots.
Mathieu Chartier5f257b12017-02-03 14:47:36 -0800361 for (auto& it : object_logs_) {
Mathieu Chartierbb87e0f2015-04-03 11:21:55 -0700362 it.second.VisitRoots(visitor);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100363 mirror::Object* old_root = it.first;
Mathieu Chartier815873e2014-02-13 18:02:13 -0800364 mirror::Object* new_root = old_root;
Mathieu Chartierbb87e0f2015-04-03 11:21:55 -0700365 visitor->VisitRoot(&new_root, RootInfo(kRootUnknown));
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100366 if (new_root != old_root) {
367 moving_roots.push_back(std::make_pair(old_root, new_root));
368 }
369 }
370
371 // Update object logs with moving roots.
372 for (const ObjectPair& pair : moving_roots) {
373 mirror::Object* old_root = pair.first;
374 mirror::Object* new_root = pair.second;
375 auto old_root_it = object_logs_.find(old_root);
376 CHECK(old_root_it != object_logs_.end());
377 CHECK(object_logs_.find(new_root) == object_logs_.end());
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800378 object_logs_.emplace(new_root, std::move(old_root_it->second));
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100379 object_logs_.erase(old_root_it);
380 }
381}
382
Mathieu Chartierbb87e0f2015-04-03 11:21:55 -0700383void Transaction::VisitArrayLogs(RootVisitor* visitor) {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100384 // List of moving roots.
Andreas Gampec55bb392018-09-21 00:02:02 +0000385 using ArrayPair = std::pair<mirror::Array*, mirror::Array*>;
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100386 std::list<ArrayPair> moving_roots;
387
Mathieu Chartier5f257b12017-02-03 14:47:36 -0800388 for (auto& it : array_logs_) {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100389 mirror::Array* old_root = it.first;
Sebastien Hertzee1d79a2014-02-21 15:46:30 +0100390 CHECK(!old_root->IsObjectArray());
Mathieu Chartier815873e2014-02-13 18:02:13 -0800391 mirror::Array* new_root = old_root;
Mathieu Chartierbb87e0f2015-04-03 11:21:55 -0700392 visitor->VisitRoot(reinterpret_cast<mirror::Object**>(&new_root), RootInfo(kRootUnknown));
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100393 if (new_root != old_root) {
394 moving_roots.push_back(std::make_pair(old_root, new_root));
395 }
396 }
397
398 // Update array logs with moving roots.
399 for (const ArrayPair& pair : moving_roots) {
400 mirror::Array* old_root = pair.first;
401 mirror::Array* new_root = pair.second;
402 auto old_root_it = array_logs_.find(old_root);
403 CHECK(old_root_it != array_logs_.end());
404 CHECK(array_logs_.find(new_root) == array_logs_.end());
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800405 array_logs_.emplace(new_root, std::move(old_root_it->second));
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100406 array_logs_.erase(old_root_it);
407 }
408}
409
Mathieu Chartierbb816d62016-09-07 10:17:46 -0700410void Transaction::VisitInternStringLogs(RootVisitor* visitor) {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100411 for (InternStringLog& log : intern_string_logs_) {
Mathieu Chartierbb87e0f2015-04-03 11:21:55 -0700412 log.VisitRoots(visitor);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100413 }
414}
415
Mathieu Chartierbb816d62016-09-07 10:17:46 -0700416void Transaction::VisitResolveStringLogs(RootVisitor* visitor) {
417 for (ResolveStringLog& log : resolve_string_logs_) {
418 log.VisitRoots(visitor);
419 }
420}
421
Fred Shih37f05ef2014-07-16 18:38:08 -0700422void Transaction::ObjectLog::LogBooleanValue(MemberOffset offset, uint8_t value, bool is_volatile) {
423 LogValue(ObjectLog::kBoolean, offset, value, is_volatile);
424}
425
426void Transaction::ObjectLog::LogByteValue(MemberOffset offset, int8_t value, bool is_volatile) {
427 LogValue(ObjectLog::kByte, offset, value, is_volatile);
428}
429
430void Transaction::ObjectLog::LogCharValue(MemberOffset offset, uint16_t value, bool is_volatile) {
431 LogValue(ObjectLog::kChar, offset, value, is_volatile);
432}
433
434void Transaction::ObjectLog::LogShortValue(MemberOffset offset, int16_t value, bool is_volatile) {
435 LogValue(ObjectLog::kShort, offset, value, is_volatile);
436}
437
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100438void Transaction::ObjectLog::Log32BitsValue(MemberOffset offset, uint32_t value, bool is_volatile) {
Fred Shih37f05ef2014-07-16 18:38:08 -0700439 LogValue(ObjectLog::k32Bits, offset, value, is_volatile);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100440}
441
442void Transaction::ObjectLog::Log64BitsValue(MemberOffset offset, uint64_t value, bool is_volatile) {
Fred Shih37f05ef2014-07-16 18:38:08 -0700443 LogValue(ObjectLog::k64Bits, offset, value, is_volatile);
444}
445
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800446void Transaction::ObjectLog::LogReferenceValue(MemberOffset offset,
447 mirror::Object* obj,
448 bool is_volatile) {
Fred Shih37f05ef2014-07-16 18:38:08 -0700449 LogValue(ObjectLog::kReference, offset, reinterpret_cast<uintptr_t>(obj), is_volatile);
450}
451
452void Transaction::ObjectLog::LogValue(ObjectLog::FieldValueKind kind,
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800453 MemberOffset offset,
454 uint64_t value,
455 bool is_volatile) {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100456 auto it = field_values_.find(offset.Uint32Value());
457 if (it == field_values_.end()) {
458 ObjectLog::FieldValue field_value;
459 field_value.value = value;
460 field_value.is_volatile = is_volatile;
Fred Shih37f05ef2014-07-16 18:38:08 -0700461 field_value.kind = kind;
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800462 field_values_.emplace(offset.Uint32Value(), std::move(field_value));
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100463 }
464}
465
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800466void Transaction::ObjectLog::Undo(mirror::Object* obj) const {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100467 for (auto& it : field_values_) {
468 // Garbage collector needs to access object's class and array's length. So we don't rollback
469 // these values.
470 MemberOffset field_offset(it.first);
471 if (field_offset.Uint32Value() == mirror::Class::ClassOffset().Uint32Value()) {
472 // Skip Object::class field.
473 continue;
474 }
475 if (obj->IsArrayInstance() &&
476 field_offset.Uint32Value() == mirror::Array::LengthOffset().Uint32Value()) {
477 // Skip Array::length field.
478 continue;
479 }
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800480 const FieldValue& field_value = it.second;
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100481 UndoFieldWrite(obj, field_offset, field_value);
482 }
483}
484
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800485void Transaction::ObjectLog::UndoFieldWrite(mirror::Object* obj,
486 MemberOffset field_offset,
487 const FieldValue& field_value) const {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100488 // TODO We may want to abort a transaction while still being in transaction mode. In this case,
489 // we'd need to disable the check.
Chang Xing605fe242017-07-20 15:57:21 -0700490 constexpr bool kCheckTransaction = false;
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100491 switch (field_value.kind) {
Fred Shih37f05ef2014-07-16 18:38:08 -0700492 case kBoolean:
493 if (UNLIKELY(field_value.is_volatile)) {
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800494 obj->SetFieldBooleanVolatile<false, kCheckTransaction>(
495 field_offset,
Andreas Gampe7c5acbb2018-09-20 13:54:52 -0700496 field_value.value);
Fred Shih37f05ef2014-07-16 18:38:08 -0700497 } else {
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800498 obj->SetFieldBoolean<false, kCheckTransaction>(
499 field_offset,
Andreas Gampe7c5acbb2018-09-20 13:54:52 -0700500 field_value.value);
Fred Shih37f05ef2014-07-16 18:38:08 -0700501 }
502 break;
503 case kByte:
504 if (UNLIKELY(field_value.is_volatile)) {
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800505 obj->SetFieldByteVolatile<false, kCheckTransaction>(
506 field_offset,
507 static_cast<int8_t>(field_value.value));
Fred Shih37f05ef2014-07-16 18:38:08 -0700508 } else {
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800509 obj->SetFieldByte<false, kCheckTransaction>(
510 field_offset,
511 static_cast<int8_t>(field_value.value));
Fred Shih37f05ef2014-07-16 18:38:08 -0700512 }
513 break;
514 case kChar:
515 if (UNLIKELY(field_value.is_volatile)) {
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800516 obj->SetFieldCharVolatile<false, kCheckTransaction>(
517 field_offset,
518 static_cast<uint16_t>(field_value.value));
Fred Shih37f05ef2014-07-16 18:38:08 -0700519 } else {
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800520 obj->SetFieldChar<false, kCheckTransaction>(
521 field_offset,
522 static_cast<uint16_t>(field_value.value));
Fred Shih37f05ef2014-07-16 18:38:08 -0700523 }
524 break;
525 case kShort:
526 if (UNLIKELY(field_value.is_volatile)) {
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800527 obj->SetFieldShortVolatile<false, kCheckTransaction>(
528 field_offset,
529 static_cast<int16_t>(field_value.value));
Fred Shih37f05ef2014-07-16 18:38:08 -0700530 } else {
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800531 obj->SetFieldShort<false, kCheckTransaction>(
532 field_offset,
533 static_cast<int16_t>(field_value.value));
Fred Shih37f05ef2014-07-16 18:38:08 -0700534 }
535 break;
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100536 case k32Bits:
Ian Rogersb0fa5dc2014-04-28 16:47:08 -0700537 if (UNLIKELY(field_value.is_volatile)) {
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800538 obj->SetField32Volatile<false, kCheckTransaction>(
539 field_offset,
540 static_cast<uint32_t>(field_value.value));
Ian Rogersb0fa5dc2014-04-28 16:47:08 -0700541 } else {
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800542 obj->SetField32<false, kCheckTransaction>(
543 field_offset,
544 static_cast<uint32_t>(field_value.value));
Ian Rogersb0fa5dc2014-04-28 16:47:08 -0700545 }
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100546 break;
547 case k64Bits:
Ian Rogersb0fa5dc2014-04-28 16:47:08 -0700548 if (UNLIKELY(field_value.is_volatile)) {
549 obj->SetField64Volatile<false, kCheckTransaction>(field_offset, field_value.value);
550 } else {
551 obj->SetField64<false, kCheckTransaction>(field_offset, field_value.value);
552 }
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100553 break;
554 case kReference:
Ian Rogersb0fa5dc2014-04-28 16:47:08 -0700555 if (UNLIKELY(field_value.is_volatile)) {
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800556 obj->SetFieldObjectVolatile<false, kCheckTransaction>(
557 field_offset,
558 reinterpret_cast<mirror::Object*>(field_value.value));
Ian Rogersb0fa5dc2014-04-28 16:47:08 -0700559 } else {
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800560 obj->SetFieldObject<false, kCheckTransaction>(
561 field_offset,
562 reinterpret_cast<mirror::Object*>(field_value.value));
Ian Rogersb0fa5dc2014-04-28 16:47:08 -0700563 }
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100564 break;
565 default:
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700566 LOG(FATAL) << "Unknown value kind " << static_cast<int>(field_value.kind);
Elliott Hughesc1896c92018-11-29 11:33:18 -0800567 UNREACHABLE();
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100568 }
569}
570
Mathieu Chartierbb87e0f2015-04-03 11:21:55 -0700571void Transaction::ObjectLog::VisitRoots(RootVisitor* visitor) {
Mathieu Chartier5f257b12017-02-03 14:47:36 -0800572 for (auto& it : field_values_) {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100573 FieldValue& field_value = it.second;
574 if (field_value.kind == ObjectLog::kReference) {
Mathieu Chartierbb87e0f2015-04-03 11:21:55 -0700575 visitor->VisitRootIfNonNull(reinterpret_cast<mirror::Object**>(&field_value.value),
576 RootInfo(kRootUnknown));
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100577 }
578 }
579}
580
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800581void Transaction::InternStringLog::Undo(InternTable* intern_table) const {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100582 DCHECK(intern_table != nullptr);
583 switch (string_op_) {
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700584 case InternStringLog::kInsert: {
585 switch (string_kind_) {
586 case InternStringLog::kStrongString:
Mathieu Chartier9e868092016-10-31 14:58:04 -0700587 intern_table->RemoveStrongFromTransaction(str_.Read());
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700588 break;
589 case InternStringLog::kWeakString:
Mathieu Chartier9e868092016-10-31 14:58:04 -0700590 intern_table->RemoveWeakFromTransaction(str_.Read());
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700591 break;
592 default:
593 LOG(FATAL) << "Unknown interned string kind";
Elliott Hughesc1896c92018-11-29 11:33:18 -0800594 UNREACHABLE();
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100595 }
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700596 break;
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100597 }
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700598 case InternStringLog::kRemove: {
599 switch (string_kind_) {
600 case InternStringLog::kStrongString:
Mathieu Chartier9e868092016-10-31 14:58:04 -0700601 intern_table->InsertStrongFromTransaction(str_.Read());
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700602 break;
603 case InternStringLog::kWeakString:
Mathieu Chartier9e868092016-10-31 14:58:04 -0700604 intern_table->InsertWeakFromTransaction(str_.Read());
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700605 break;
606 default:
607 LOG(FATAL) << "Unknown interned string kind";
Elliott Hughesc1896c92018-11-29 11:33:18 -0800608 UNREACHABLE();
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700609 }
610 break;
611 }
612 default:
613 LOG(FATAL) << "Unknown interned string op";
Elliott Hughesc1896c92018-11-29 11:33:18 -0800614 UNREACHABLE();
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700615 }
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100616}
617
Mathieu Chartierbb87e0f2015-04-03 11:21:55 -0700618void Transaction::InternStringLog::VisitRoots(RootVisitor* visitor) {
Mathieu Chartier9e868092016-10-31 14:58:04 -0700619 str_.VisitRoot(visitor, RootInfo(kRootInternedString));
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100620}
621
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800622void Transaction::ResolveStringLog::Undo() const {
Mathieu Chartierbb816d62016-09-07 10:17:46 -0700623 dex_cache_.Read()->ClearString(string_idx_);
624}
625
Mathieu Chartier9e868092016-10-31 14:58:04 -0700626Transaction::ResolveStringLog::ResolveStringLog(ObjPtr<mirror::DexCache> dex_cache,
Andreas Gampe8a0128a2016-11-28 07:38:35 -0800627 dex::StringIndex string_idx)
Mathieu Chartierbb816d62016-09-07 10:17:46 -0700628 : dex_cache_(dex_cache),
629 string_idx_(string_idx) {
630 DCHECK(dex_cache != nullptr);
Andreas Gampe8a0128a2016-11-28 07:38:35 -0800631 DCHECK_LT(string_idx_.index_, dex_cache->GetDexFile()->NumStringIds());
Mathieu Chartierbb816d62016-09-07 10:17:46 -0700632}
633
634void Transaction::ResolveStringLog::VisitRoots(RootVisitor* visitor) {
635 dex_cache_.VisitRoot(visitor, RootInfo(kRootVMInternal));
636}
637
Mathieu Chartier9e868092016-10-31 14:58:04 -0700638Transaction::InternStringLog::InternStringLog(ObjPtr<mirror::String> s,
639 StringKind kind,
640 StringOp op)
641 : str_(s),
642 string_kind_(kind),
643 string_op_(op) {
644 DCHECK(s != nullptr);
645}
646
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100647void Transaction::ArrayLog::LogValue(size_t index, uint64_t value) {
648 auto it = array_values_.find(index);
649 if (it == array_values_.end()) {
650 array_values_.insert(std::make_pair(index, value));
651 }
652}
653
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800654void Transaction::ArrayLog::Undo(mirror::Array* array) const {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100655 DCHECK(array != nullptr);
656 DCHECK(array->IsArrayInstance());
657 Primitive::Type type = array->GetClass()->GetComponentType()->GetPrimitiveType();
658 for (auto it : array_values_) {
659 UndoArrayWrite(array, type, it.first, it.second);
660 }
661}
662
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800663void Transaction::ArrayLog::UndoArrayWrite(mirror::Array* array,
664 Primitive::Type array_type,
665 size_t index,
666 uint64_t value) const {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100667 // TODO We may want to abort a transaction while still being in transaction mode. In this case,
668 // we'd need to disable the check.
Chang Xing605fe242017-07-20 15:57:21 -0700669 constexpr bool kCheckTransaction = false;
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100670 switch (array_type) {
671 case Primitive::kPrimBoolean:
Chang Xing605fe242017-07-20 15:57:21 -0700672 array->AsBooleanArray()->SetWithoutChecks<false, kCheckTransaction>(
673 index, static_cast<uint8_t>(value));
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100674 break;
675 case Primitive::kPrimByte:
Chang Xing605fe242017-07-20 15:57:21 -0700676 array->AsByteArray()->SetWithoutChecks<false, kCheckTransaction>(
677 index, static_cast<int8_t>(value));
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100678 break;
679 case Primitive::kPrimChar:
Chang Xing605fe242017-07-20 15:57:21 -0700680 array->AsCharArray()->SetWithoutChecks<false, kCheckTransaction>(
681 index, static_cast<uint16_t>(value));
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100682 break;
683 case Primitive::kPrimShort:
Chang Xing605fe242017-07-20 15:57:21 -0700684 array->AsShortArray()->SetWithoutChecks<false, kCheckTransaction>(
685 index, static_cast<int16_t>(value));
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100686 break;
687 case Primitive::kPrimInt:
Chang Xing605fe242017-07-20 15:57:21 -0700688 array->AsIntArray()->SetWithoutChecks<false, kCheckTransaction>(
689 index, static_cast<int32_t>(value));
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100690 break;
691 case Primitive::kPrimFloat:
Chang Xing605fe242017-07-20 15:57:21 -0700692 array->AsFloatArray()->SetWithoutChecks<false, kCheckTransaction>(
693 index, static_cast<float>(value));
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100694 break;
695 case Primitive::kPrimLong:
Chang Xing605fe242017-07-20 15:57:21 -0700696 array->AsLongArray()->SetWithoutChecks<false, kCheckTransaction>(
697 index, static_cast<int64_t>(value));
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100698 break;
699 case Primitive::kPrimDouble:
Chang Xing605fe242017-07-20 15:57:21 -0700700 array->AsDoubleArray()->SetWithoutChecks<false, kCheckTransaction>(
701 index, static_cast<double>(value));
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100702 break;
Sebastien Hertzee1d79a2014-02-21 15:46:30 +0100703 case Primitive::kPrimNot:
704 LOG(FATAL) << "ObjectArray should be treated as Object";
Elliott Hughesc1896c92018-11-29 11:33:18 -0800705 UNREACHABLE();
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100706 default:
707 LOG(FATAL) << "Unsupported type " << array_type;
Elliott Hughesc1896c92018-11-29 11:33:18 -0800708 UNREACHABLE();
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100709 }
710}
711
Vladimir Markob68bb7a2020-03-17 10:55:25 +0000712Transaction* ScopedAssertNoNewTransactionRecords::InstallAssertion(const char* reason) {
713 Transaction* transaction = nullptr;
714 if (kIsDebugBuild && Runtime::Current()->IsActiveTransaction()) {
715 transaction = Runtime::Current()->GetTransaction().get();
716 if (transaction != nullptr) {
717 MutexLock mu(Thread::Current(), transaction->log_lock_);
718 CHECK(transaction->assert_no_new_records_reason_ == nullptr)
719 << "old: " << transaction->assert_no_new_records_reason_ << " new: " << reason;
720 transaction->assert_no_new_records_reason_ = reason;
721 }
722 }
723 return transaction;
724}
725
726void ScopedAssertNoNewTransactionRecords::RemoveAssertion(Transaction* transaction) {
727 if (kIsDebugBuild) {
728 CHECK(Runtime::Current()->GetTransaction().get() == transaction);
729 MutexLock mu(Thread::Current(), transaction->log_lock_);
730 CHECK(transaction->assert_no_new_records_reason_ != nullptr);
731 transaction->assert_no_new_records_reason_ = nullptr;
732 }
733}
734
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100735} // namespace art