blob: 193c1119b8bd2176dbffd65fa44b40bfa82ea434 [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"
Vladimir Marko0685b982021-03-25 11:59:22 +000024#include "dex/descriptors_names.h"
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +010025#include "gc/accounting/card_table-inl.h"
Vladimir Marko672c0802019-07-26 13:03:13 +010026#include "gc/heap.h"
Andreas Gampe508fdf32017-06-05 16:42:13 -070027#include "gc_root-inl.h"
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +010028#include "intern_table.h"
Mathieu Chartiere401d142015-04-22 13:56:20 -070029#include "mirror/class-inl.h"
Andreas Gampe508fdf32017-06-05 16:42:13 -070030#include "mirror/dex_cache-inl.h"
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +010031#include "mirror/object-inl.h"
32#include "mirror/object_array-inl.h"
Vladimir Marko672c0802019-07-26 13:03:13 +010033#include "obj_ptr-inl.h"
34#include "runtime.h"
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +010035
36#include <list>
37
38namespace art {
39
40// TODO: remove (only used for debugging purpose).
41static constexpr bool kEnableTransactionStats = false;
42
Vladimir Markob6e67922021-07-06 15:53:07 +010043Transaction::Transaction(bool strict,
44 mirror::Class* root,
45 ArenaStack* arena_stack,
46 ArenaPool* arena_pool)
47 : arena_stack_(std::nullopt),
48 allocator_(arena_stack != nullptr ? arena_stack : &arena_stack_.emplace(arena_pool)),
49 object_logs_(std::less<mirror::Object*>(), allocator_.Adapter(kArenaAllocTransaction)),
50 array_logs_(std::less<mirror::Array*>(), allocator_.Adapter(kArenaAllocTransaction)),
51 intern_string_logs_(allocator_.Adapter(kArenaAllocTransaction)),
52 resolve_string_logs_(allocator_.Adapter(kArenaAllocTransaction)),
53 resolve_method_type_logs_(allocator_.Adapter(kArenaAllocTransaction)),
54 aborted_(false),
Vladimir Marko672c0802019-07-26 13:03:13 +010055 rolling_back_(false),
Vladimir Marko4d7b6892020-01-16 17:06:35 +000056 heap_(Runtime::Current()->GetHeap()),
57 strict_(strict),
Vladimir Markob68bb7a2020-03-17 10:55:25 +000058 root_(root),
59 assert_no_new_records_reason_(nullptr) {
Vladimir Marko672c0802019-07-26 13:03:13 +010060 DCHECK(Runtime::Current()->IsAotCompiler());
Vladimir Markob6e67922021-07-06 15:53:07 +010061 DCHECK_NE(arena_stack != nullptr, arena_pool != nullptr);
Chang Xingcade5c32017-07-20 17:56:26 -070062}
63
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +010064Transaction::~Transaction() {
65 if (kEnableTransactionStats) {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +010066 size_t objects_count = object_logs_.size();
67 size_t field_values_count = 0;
Mathieu Chartier38e954c2017-02-03 16:06:35 -080068 for (const auto& it : object_logs_) {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +010069 field_values_count += it.second.Size();
70 }
71 size_t array_count = array_logs_.size();
72 size_t array_values_count = 0;
Mathieu Chartier38e954c2017-02-03 16:06:35 -080073 for (const auto& it : array_logs_) {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +010074 array_values_count += it.second.Size();
75 }
Vladimir Markob6e67922021-07-06 15:53:07 +010076 size_t intern_string_count =
77 std::distance(intern_string_logs_.begin(), intern_string_logs_.end());
78 size_t resolve_string_count =
79 std::distance(resolve_string_logs_.begin(), resolve_string_logs_.end());
80 size_t resolve_method_type_count =
81 std::distance(resolve_method_type_logs_.begin(), resolve_method_type_logs_.end());
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +010082 LOG(INFO) << "Transaction::~Transaction"
83 << ": objects_count=" << objects_count
84 << ", field_values_count=" << field_values_count
85 << ", array_count=" << array_count
86 << ", array_values_count=" << array_values_count
Mathieu Chartierbb816d62016-09-07 10:17:46 -070087 << ", intern_string_count=" << intern_string_count
Vladimir Markob6e67922021-07-06 15:53:07 +010088 << ", resolve_string_count=" << resolve_string_count
89 << ", resolve_method_type_count=" << resolve_method_type_count;
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +010090 }
91}
92
Sebastien Hertz1c80bec2015-02-03 11:58:06 +010093void Transaction::Abort(const std::string& abort_message) {
Sebastien Hertz2fd7e692015-04-02 11:11:19 +020094 // We may abort more than once if the exception thrown at the time of the
95 // previous abort has been caught during execution of a class initializer.
Sebastien Hertz1c80bec2015-02-03 11:58:06 +010096 // We just keep the message of the first abort because it will cause the
97 // transaction to be rolled back anyway.
98 if (!aborted_) {
99 aborted_ = true;
100 abort_message_ = abort_message;
101 }
102}
103
Sebastien Hertzb81e1cd2015-04-28 12:31:41 +0200104void Transaction::ThrowAbortError(Thread* self, const std::string* abort_message) {
105 const bool rethrow = (abort_message == nullptr);
Sebastien Hertzbd9cf9f2015-03-03 12:16:13 +0100106 if (kIsDebugBuild && rethrow) {
Vladimir Marko0685b982021-03-25 11:59:22 +0000107 CHECK(IsAborted()) << "Rethrow " << DescriptorToDot(Transaction::kAbortExceptionDescriptor)
Sebastien Hertz2fd7e692015-04-02 11:11:19 +0200108 << " while transaction is not aborted";
Sebastien Hertzbd9cf9f2015-03-03 12:16:13 +0100109 }
Sebastien Hertzb81e1cd2015-04-28 12:31:41 +0200110 if (rethrow) {
111 // Rethrow an exception with the earlier abort message stored in the transaction.
Vladimir Marko0685b982021-03-25 11:59:22 +0000112 self->ThrowNewWrappedException(Transaction::kAbortExceptionDescriptor,
Sebastien Hertzb81e1cd2015-04-28 12:31:41 +0200113 GetAbortMessage().c_str());
114 } else {
115 // Throw an exception with the given abort message.
Vladimir Marko0685b982021-03-25 11:59:22 +0000116 self->ThrowNewWrappedException(Transaction::kAbortExceptionDescriptor,
Sebastien Hertzb81e1cd2015-04-28 12:31:41 +0200117 abort_message->c_str());
118 }
Sebastien Hertz1c80bec2015-02-03 11:58:06 +0100119}
120
Vladimir Marko24c080f2021-07-06 14:04:30 +0100121const std::string& Transaction::GetAbortMessage() const {
Sebastien Hertz1c80bec2015-02-03 11:58:06 +0100122 return abort_message_;
123}
124
Vladimir Marko24c080f2021-07-06 14:04:30 +0100125bool Transaction::WriteConstraint(ObjPtr<mirror::Object> obj) const {
Vladimir Marko4d7b6892020-01-16 17:06:35 +0000126 DCHECK(obj != nullptr);
Vladimir Marko4d7b6892020-01-16 17:06:35 +0000127
128 // Prevent changes in boot image spaces for app or boot image extension.
129 // For boot image there are no boot image spaces and this condition evaluates to false.
130 if (heap_->ObjectIsInBootImageSpace(obj)) {
131 return true;
Chang Xingbd208d82017-07-12 14:53:17 -0700132 }
Vladimir Marko4d7b6892020-01-16 17:06:35 +0000133
134 // For apps, also prevent writing to other classes.
135 return IsStrict() &&
136 obj->IsClass() && // no constraint updating instances or arrays
137 obj != root_; // modifying other classes' static field, fail
Chang Xingbd208d82017-07-12 14:53:17 -0700138}
139
Vladimir Marko24c080f2021-07-06 14:04:30 +0100140bool Transaction::WriteValueConstraint(ObjPtr<mirror::Object> value) const {
Vladimir Marko149cdda2019-11-12 15:02:51 +0000141 if (value == nullptr) {
142 return false; // We can always store null values.
143 }
144 gc::Heap* heap = Runtime::Current()->GetHeap();
Vladimir Marko149cdda2019-11-12 15:02:51 +0000145 if (IsStrict()) {
146 // TODO: Should we restrict writes the same way as for boot image extension?
147 return false;
148 } else if (heap->GetBootImageSpaces().empty()) {
149 return false; // No constraints for boot image.
150 } else {
151 // Boot image extension.
Vladimir Marko149cdda2019-11-12 15:02:51 +0000152 ObjPtr<mirror::Class> klass = value->IsClass() ? value->AsClass() : value->GetClass();
Vladimir Marko7ed2d382019-11-25 10:41:53 +0000153 return !AotClassLinker::CanReferenceInBootImageExtension(klass, heap);
Vladimir Marko149cdda2019-11-12 15:02:51 +0000154 }
155}
156
Vladimir Marko24c080f2021-07-06 14:04:30 +0100157bool Transaction::ReadConstraint(ObjPtr<mirror::Object> obj) const {
Vladimir Marko4d7b6892020-01-16 17:06:35 +0000158 // Read constraints are checked only for static field reads as there are
159 // no constraints on reading instance fields and array elements.
Chang Xingbd208d82017-07-12 14:53:17 -0700160 DCHECK(obj->IsClass());
Vladimir Marko672c0802019-07-26 13:03:13 +0100161 if (IsStrict()) {
162 return obj != root_; // fail if not self-updating
163 } else {
164 // For boot image and boot image extension, allow reading any field.
Chang Xingbd208d82017-07-12 14:53:17 -0700165 return false;
166 }
Chang Xingbd208d82017-07-12 14:53:17 -0700167}
168
Vladimir Markob6e67922021-07-06 15:53:07 +0100169inline Transaction::ObjectLog& Transaction::GetOrCreateObjectLog(mirror::Object* obj) {
170 return object_logs_.GetOrCreate(obj, [&]() { return ObjectLog(&allocator_); });
171}
172
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800173void Transaction::RecordWriteFieldBoolean(mirror::Object* obj,
174 MemberOffset field_offset,
175 uint8_t value,
176 bool is_volatile) {
Fred Shih37f05ef2014-07-16 18:38:08 -0700177 DCHECK(obj != nullptr);
Vladimir Markob68bb7a2020-03-17 10:55:25 +0000178 DCHECK(assert_no_new_records_reason_ == nullptr) << assert_no_new_records_reason_;
Vladimir Markob6e67922021-07-06 15:53:07 +0100179 ObjectLog& object_log = GetOrCreateObjectLog(obj);
Fred Shih37f05ef2014-07-16 18:38:08 -0700180 object_log.LogBooleanValue(field_offset, value, is_volatile);
181}
182
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800183void Transaction::RecordWriteFieldByte(mirror::Object* obj,
184 MemberOffset field_offset,
185 int8_t value,
186 bool is_volatile) {
Fred Shih37f05ef2014-07-16 18:38:08 -0700187 DCHECK(obj != nullptr);
Vladimir Markob68bb7a2020-03-17 10:55:25 +0000188 DCHECK(assert_no_new_records_reason_ == nullptr) << assert_no_new_records_reason_;
Vladimir Markob6e67922021-07-06 15:53:07 +0100189 ObjectLog& object_log = GetOrCreateObjectLog(obj);
Fred Shih37f05ef2014-07-16 18:38:08 -0700190 object_log.LogByteValue(field_offset, value, is_volatile);
191}
192
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800193void Transaction::RecordWriteFieldChar(mirror::Object* obj,
194 MemberOffset field_offset,
195 uint16_t value,
196 bool is_volatile) {
Fred Shih37f05ef2014-07-16 18:38:08 -0700197 DCHECK(obj != nullptr);
Vladimir Markob68bb7a2020-03-17 10:55:25 +0000198 DCHECK(assert_no_new_records_reason_ == nullptr) << assert_no_new_records_reason_;
Vladimir Markob6e67922021-07-06 15:53:07 +0100199 ObjectLog& object_log = GetOrCreateObjectLog(obj);
Fred Shih37f05ef2014-07-16 18:38:08 -0700200 object_log.LogCharValue(field_offset, value, is_volatile);
201}
202
203
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800204void Transaction::RecordWriteFieldShort(mirror::Object* obj,
205 MemberOffset field_offset,
206 int16_t value,
207 bool is_volatile) {
Fred Shih37f05ef2014-07-16 18:38:08 -0700208 DCHECK(obj != nullptr);
Vladimir Markob68bb7a2020-03-17 10:55:25 +0000209 DCHECK(assert_no_new_records_reason_ == nullptr) << assert_no_new_records_reason_;
Vladimir Markob6e67922021-07-06 15:53:07 +0100210 ObjectLog& object_log = GetOrCreateObjectLog(obj);
Fred Shih37f05ef2014-07-16 18:38:08 -0700211 object_log.LogShortValue(field_offset, value, is_volatile);
212}
213
214
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800215void Transaction::RecordWriteField32(mirror::Object* obj,
216 MemberOffset field_offset,
217 uint32_t value,
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100218 bool is_volatile) {
219 DCHECK(obj != nullptr);
Vladimir Markob68bb7a2020-03-17 10:55:25 +0000220 DCHECK(assert_no_new_records_reason_ == nullptr) << assert_no_new_records_reason_;
Vladimir Markob6e67922021-07-06 15:53:07 +0100221 ObjectLog& object_log = GetOrCreateObjectLog(obj);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100222 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);
Vladimir Markob68bb7a2020-03-17 10:55:25 +0000230 DCHECK(assert_no_new_records_reason_ == nullptr) << assert_no_new_records_reason_;
Vladimir Markob6e67922021-07-06 15:53:07 +0100231 ObjectLog& object_log = GetOrCreateObjectLog(obj);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100232 object_log.Log64BitsValue(field_offset, value, is_volatile);
233}
234
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800235void Transaction::RecordWriteFieldReference(mirror::Object* obj,
236 MemberOffset field_offset,
237 mirror::Object* value,
238 bool is_volatile) {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100239 DCHECK(obj != nullptr);
Vladimir Markob68bb7a2020-03-17 10:55:25 +0000240 DCHECK(assert_no_new_records_reason_ == nullptr) << assert_no_new_records_reason_;
Vladimir Markob6e67922021-07-06 15:53:07 +0100241 ObjectLog& object_log = GetOrCreateObjectLog(obj);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100242 object_log.LogReferenceValue(field_offset, value, is_volatile);
243}
244
245void Transaction::RecordWriteArray(mirror::Array* array, size_t index, uint64_t value) {
246 DCHECK(array != nullptr);
247 DCHECK(array->IsArrayInstance());
Sebastien Hertzee1d79a2014-02-21 15:46:30 +0100248 DCHECK(!array->IsObjectArray());
Vladimir Markob68bb7a2020-03-17 10:55:25 +0000249 DCHECK(assert_no_new_records_reason_ == nullptr) << assert_no_new_records_reason_;
Vladimir Markob6e67922021-07-06 15:53:07 +0100250 ArrayLog& array_log = array_logs_.GetOrCreate(array, [&]() { return ArrayLog(&allocator_); });
251 array_log.LogValue(index, value);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100252}
253
Andreas Gampe8a0128a2016-11-28 07:38:35 -0800254void Transaction::RecordResolveString(ObjPtr<mirror::DexCache> dex_cache,
255 dex::StringIndex string_idx) {
Mathieu Chartierbb816d62016-09-07 10:17:46 -0700256 DCHECK(dex_cache != nullptr);
Andreas Gampe8a0128a2016-11-28 07:38:35 -0800257 DCHECK_LT(string_idx.index_, dex_cache->GetDexFile()->NumStringIds());
Vladimir Markob68bb7a2020-03-17 10:55:25 +0000258 DCHECK(assert_no_new_records_reason_ == nullptr) << assert_no_new_records_reason_;
Vladimir Markob6e67922021-07-06 15:53:07 +0100259 resolve_string_logs_.emplace_front(dex_cache, string_idx);
Mathieu Chartierbb816d62016-09-07 10:17:46 -0700260}
261
Vladimir Markoe9a4a602021-06-22 16:33:34 +0100262void Transaction::RecordResolveMethodType(ObjPtr<mirror::DexCache> dex_cache,
263 dex::ProtoIndex proto_idx) {
264 DCHECK(dex_cache != nullptr);
265 DCHECK_LT(proto_idx.index_, dex_cache->GetDexFile()->NumProtoIds());
Vladimir Markoe9a4a602021-06-22 16:33:34 +0100266 DCHECK(assert_no_new_records_reason_ == nullptr) << assert_no_new_records_reason_;
Vladimir Markob6e67922021-07-06 15:53:07 +0100267 resolve_method_type_logs_.emplace_front(dex_cache, proto_idx);
Vladimir Markoe9a4a602021-06-22 16:33:34 +0100268}
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());
Vladimir Markob68bb7a2020-03-17 10:55:25 +0000292 DCHECK(assert_no_new_records_reason_ == nullptr) << assert_no_new_records_reason_;
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800293 intern_string_logs_.push_front(std::move(log));
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100294}
295
Sebastien Hertz1c80bec2015-02-03 11:58:06 +0100296void Transaction::Rollback() {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100297 Thread* self = Thread::Current();
298 self->AssertNoPendingException();
Vladimir Marko24c080f2021-07-06 14:04:30 +0100299 MutexLock mu(self, *Locks::intern_table_lock_);
Chang Xing605fe242017-07-20 15:57:21 -0700300 rolling_back_ = true;
301 CHECK(!Runtime::Current()->IsActiveTransaction());
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100302 UndoObjectModifications();
303 UndoArrayModifications();
304 UndoInternStringTableModifications();
Mathieu Chartierbb816d62016-09-07 10:17:46 -0700305 UndoResolveStringModifications();
Vladimir Markoe9a4a602021-06-22 16:33:34 +0100306 UndoResolveMethodTypeModifications();
Chang Xing605fe242017-07-20 15:57:21 -0700307 rolling_back_ = false;
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100308}
309
310void Transaction::UndoObjectModifications() {
311 // TODO we may not need to restore objects allocated during this transaction. Or we could directly
312 // remove them from the heap.
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800313 for (const auto& it : object_logs_) {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100314 it.second.Undo(it.first);
315 }
316 object_logs_.clear();
317}
318
319void Transaction::UndoArrayModifications() {
320 // TODO we may not need to restore array allocated during this transaction. Or we could directly
321 // remove them from the heap.
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800322 for (const auto& it : array_logs_) {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100323 it.second.Undo(it.first);
324 }
325 array_logs_.clear();
326}
327
328void Transaction::UndoInternStringTableModifications() {
329 InternTable* const intern_table = Runtime::Current()->GetInternTable();
330 // We want to undo each operation from the most recent to the oldest. List has been filled so the
331 // most recent operation is at list begin so just have to iterate over it.
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800332 for (const InternStringLog& string_log : intern_string_logs_) {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100333 string_log.Undo(intern_table);
334 }
335 intern_string_logs_.clear();
336}
337
Mathieu Chartierbb816d62016-09-07 10:17:46 -0700338void Transaction::UndoResolveStringModifications() {
339 for (ResolveStringLog& string_log : resolve_string_logs_) {
340 string_log.Undo();
341 }
342 resolve_string_logs_.clear();
343}
344
Vladimir Markoe9a4a602021-06-22 16:33:34 +0100345void Transaction::UndoResolveMethodTypeModifications() {
346 for (ResolveMethodTypeLog& method_type_log : resolve_method_type_logs_) {
347 method_type_log.Undo();
348 }
349 resolve_method_type_logs_.clear();
350}
351
Mathieu Chartierbb87e0f2015-04-03 11:21:55 -0700352void Transaction::VisitRoots(RootVisitor* visitor) {
Vladimir Markob6e67922021-07-06 15:53:07 +0100353 // Transactions are used for single-threaded initialization.
354 // This is the only function that should be called from a different thread,
355 // namely the GC thread, and it is called with the mutator lock held exclusively,
356 // so the data structures in the `Transaction` are protected from concurrent use.
357 DCHECK(Locks::mutator_lock_->IsExclusiveHeld(Thread::Current()));
358
Chang Xingcade5c32017-07-20 17:56:26 -0700359 visitor->VisitRoot(reinterpret_cast<mirror::Object**>(&root_), RootInfo(kRootUnknown));
Vladimir Markob6e67922021-07-06 15:53:07 +0100360 {
361 // Create a separate `ArenaStack` for this thread.
362 ArenaStack arena_stack(Runtime::Current()->GetArenaPool());
363 VisitObjectLogs(visitor, &arena_stack);
364 VisitArrayLogs(visitor, &arena_stack);
365 }
Mathieu Chartierbb816d62016-09-07 10:17:46 -0700366 VisitInternStringLogs(visitor);
367 VisitResolveStringLogs(visitor);
Vladimir Markoe9a4a602021-06-22 16:33:34 +0100368 VisitResolveMethodTypeLogs(visitor);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100369}
370
Vladimir Markob6e67922021-07-06 15:53:07 +0100371template <typename MovingRoots, typename Container>
372void UpdateKeys(const MovingRoots& moving_roots, Container& container) {
373 for (const auto& pair : moving_roots) {
374 auto* old_root = pair.first;
375 auto* new_root = pair.second;
376 auto node = container.extract(old_root);
377 CHECK(!node.empty());
378 node.key() = new_root;
379 bool inserted = container.insert(std::move(node)).inserted;
380 CHECK(inserted);
381 }
382}
383
384void Transaction::VisitObjectLogs(RootVisitor* visitor, ArenaStack* arena_stack) {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100385 // List of moving roots.
Vladimir Markob6e67922021-07-06 15:53:07 +0100386 ScopedArenaAllocator allocator(arena_stack);
Andreas Gampec55bb392018-09-21 00:02:02 +0000387 using ObjectPair = std::pair<mirror::Object*, mirror::Object*>;
Vladimir Markob6e67922021-07-06 15:53:07 +0100388 ScopedArenaForwardList<ObjectPair> moving_roots(allocator.Adapter(kArenaAllocTransaction));
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100389
390 // Visit roots.
Mathieu Chartier5f257b12017-02-03 14:47:36 -0800391 for (auto& it : object_logs_) {
Mathieu Chartierbb87e0f2015-04-03 11:21:55 -0700392 it.second.VisitRoots(visitor);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100393 mirror::Object* old_root = it.first;
Mathieu Chartier815873e2014-02-13 18:02:13 -0800394 mirror::Object* new_root = old_root;
Mathieu Chartierbb87e0f2015-04-03 11:21:55 -0700395 visitor->VisitRoot(&new_root, RootInfo(kRootUnknown));
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100396 if (new_root != old_root) {
Vladimir Markob6e67922021-07-06 15:53:07 +0100397 moving_roots.push_front(std::make_pair(old_root, new_root));
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100398 }
399 }
400
401 // Update object logs with moving roots.
Vladimir Markob6e67922021-07-06 15:53:07 +0100402 UpdateKeys(moving_roots, object_logs_);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100403}
404
Vladimir Markob6e67922021-07-06 15:53:07 +0100405void Transaction::VisitArrayLogs(RootVisitor* visitor, ArenaStack* arena_stack) {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100406 // List of moving roots.
Vladimir Markob6e67922021-07-06 15:53:07 +0100407 ScopedArenaAllocator allocator(arena_stack);
Andreas Gampec55bb392018-09-21 00:02:02 +0000408 using ArrayPair = std::pair<mirror::Array*, mirror::Array*>;
Vladimir Markob6e67922021-07-06 15:53:07 +0100409 ScopedArenaForwardList<ArrayPair> moving_roots(allocator.Adapter(kArenaAllocTransaction));
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100410
Mathieu Chartier5f257b12017-02-03 14:47:36 -0800411 for (auto& it : array_logs_) {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100412 mirror::Array* old_root = it.first;
Sebastien Hertzee1d79a2014-02-21 15:46:30 +0100413 CHECK(!old_root->IsObjectArray());
Mathieu Chartier815873e2014-02-13 18:02:13 -0800414 mirror::Array* new_root = old_root;
Mathieu Chartierbb87e0f2015-04-03 11:21:55 -0700415 visitor->VisitRoot(reinterpret_cast<mirror::Object**>(&new_root), RootInfo(kRootUnknown));
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100416 if (new_root != old_root) {
Vladimir Markob6e67922021-07-06 15:53:07 +0100417 moving_roots.push_front(std::make_pair(old_root, new_root));
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100418 }
419 }
420
421 // Update array logs with moving roots.
Vladimir Markob6e67922021-07-06 15:53:07 +0100422 UpdateKeys(moving_roots, array_logs_);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100423}
424
Mathieu Chartierbb816d62016-09-07 10:17:46 -0700425void Transaction::VisitInternStringLogs(RootVisitor* visitor) {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100426 for (InternStringLog& log : intern_string_logs_) {
Mathieu Chartierbb87e0f2015-04-03 11:21:55 -0700427 log.VisitRoots(visitor);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100428 }
429}
430
Mathieu Chartierbb816d62016-09-07 10:17:46 -0700431void Transaction::VisitResolveStringLogs(RootVisitor* visitor) {
432 for (ResolveStringLog& log : resolve_string_logs_) {
433 log.VisitRoots(visitor);
434 }
435}
436
Vladimir Markoe9a4a602021-06-22 16:33:34 +0100437void Transaction::VisitResolveMethodTypeLogs(RootVisitor* visitor) {
438 for (ResolveMethodTypeLog& log : resolve_method_type_logs_) {
439 log.VisitRoots(visitor);
440 }
441}
442
Fred Shih37f05ef2014-07-16 18:38:08 -0700443void Transaction::ObjectLog::LogBooleanValue(MemberOffset offset, uint8_t value, bool is_volatile) {
444 LogValue(ObjectLog::kBoolean, offset, value, is_volatile);
445}
446
447void Transaction::ObjectLog::LogByteValue(MemberOffset offset, int8_t value, bool is_volatile) {
448 LogValue(ObjectLog::kByte, offset, value, is_volatile);
449}
450
451void Transaction::ObjectLog::LogCharValue(MemberOffset offset, uint16_t value, bool is_volatile) {
452 LogValue(ObjectLog::kChar, offset, value, is_volatile);
453}
454
455void Transaction::ObjectLog::LogShortValue(MemberOffset offset, int16_t value, bool is_volatile) {
456 LogValue(ObjectLog::kShort, offset, value, is_volatile);
457}
458
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100459void Transaction::ObjectLog::Log32BitsValue(MemberOffset offset, uint32_t value, bool is_volatile) {
Fred Shih37f05ef2014-07-16 18:38:08 -0700460 LogValue(ObjectLog::k32Bits, offset, value, is_volatile);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100461}
462
463void Transaction::ObjectLog::Log64BitsValue(MemberOffset offset, uint64_t value, bool is_volatile) {
Fred Shih37f05ef2014-07-16 18:38:08 -0700464 LogValue(ObjectLog::k64Bits, offset, value, is_volatile);
465}
466
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800467void Transaction::ObjectLog::LogReferenceValue(MemberOffset offset,
468 mirror::Object* obj,
469 bool is_volatile) {
Fred Shih37f05ef2014-07-16 18:38:08 -0700470 LogValue(ObjectLog::kReference, offset, reinterpret_cast<uintptr_t>(obj), is_volatile);
471}
472
473void Transaction::ObjectLog::LogValue(ObjectLog::FieldValueKind kind,
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800474 MemberOffset offset,
475 uint64_t value,
476 bool is_volatile) {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100477 auto it = field_values_.find(offset.Uint32Value());
478 if (it == field_values_.end()) {
479 ObjectLog::FieldValue field_value;
480 field_value.value = value;
481 field_value.is_volatile = is_volatile;
Fred Shih37f05ef2014-07-16 18:38:08 -0700482 field_value.kind = kind;
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800483 field_values_.emplace(offset.Uint32Value(), std::move(field_value));
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100484 }
485}
486
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800487void Transaction::ObjectLog::Undo(mirror::Object* obj) const {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100488 for (auto& it : field_values_) {
489 // Garbage collector needs to access object's class and array's length. So we don't rollback
490 // these values.
491 MemberOffset field_offset(it.first);
492 if (field_offset.Uint32Value() == mirror::Class::ClassOffset().Uint32Value()) {
493 // Skip Object::class field.
494 continue;
495 }
496 if (obj->IsArrayInstance() &&
497 field_offset.Uint32Value() == mirror::Array::LengthOffset().Uint32Value()) {
498 // Skip Array::length field.
499 continue;
500 }
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800501 const FieldValue& field_value = it.second;
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100502 UndoFieldWrite(obj, field_offset, field_value);
503 }
504}
505
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800506void Transaction::ObjectLog::UndoFieldWrite(mirror::Object* obj,
507 MemberOffset field_offset,
508 const FieldValue& field_value) const {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100509 // TODO We may want to abort a transaction while still being in transaction mode. In this case,
510 // we'd need to disable the check.
Chang Xing605fe242017-07-20 15:57:21 -0700511 constexpr bool kCheckTransaction = false;
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100512 switch (field_value.kind) {
Fred Shih37f05ef2014-07-16 18:38:08 -0700513 case kBoolean:
514 if (UNLIKELY(field_value.is_volatile)) {
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800515 obj->SetFieldBooleanVolatile<false, kCheckTransaction>(
516 field_offset,
Andreas Gampe7c5acbb2018-09-20 13:54:52 -0700517 field_value.value);
Fred Shih37f05ef2014-07-16 18:38:08 -0700518 } else {
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800519 obj->SetFieldBoolean<false, kCheckTransaction>(
520 field_offset,
Andreas Gampe7c5acbb2018-09-20 13:54:52 -0700521 field_value.value);
Fred Shih37f05ef2014-07-16 18:38:08 -0700522 }
523 break;
524 case kByte:
525 if (UNLIKELY(field_value.is_volatile)) {
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800526 obj->SetFieldByteVolatile<false, kCheckTransaction>(
527 field_offset,
528 static_cast<int8_t>(field_value.value));
Fred Shih37f05ef2014-07-16 18:38:08 -0700529 } else {
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800530 obj->SetFieldByte<false, kCheckTransaction>(
531 field_offset,
532 static_cast<int8_t>(field_value.value));
Fred Shih37f05ef2014-07-16 18:38:08 -0700533 }
534 break;
535 case kChar:
536 if (UNLIKELY(field_value.is_volatile)) {
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800537 obj->SetFieldCharVolatile<false, kCheckTransaction>(
538 field_offset,
539 static_cast<uint16_t>(field_value.value));
Fred Shih37f05ef2014-07-16 18:38:08 -0700540 } else {
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800541 obj->SetFieldChar<false, kCheckTransaction>(
542 field_offset,
543 static_cast<uint16_t>(field_value.value));
Fred Shih37f05ef2014-07-16 18:38:08 -0700544 }
545 break;
546 case kShort:
547 if (UNLIKELY(field_value.is_volatile)) {
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800548 obj->SetFieldShortVolatile<false, kCheckTransaction>(
549 field_offset,
550 static_cast<int16_t>(field_value.value));
Fred Shih37f05ef2014-07-16 18:38:08 -0700551 } else {
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800552 obj->SetFieldShort<false, kCheckTransaction>(
553 field_offset,
554 static_cast<int16_t>(field_value.value));
Fred Shih37f05ef2014-07-16 18:38:08 -0700555 }
556 break;
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100557 case k32Bits:
Ian Rogersb0fa5dc2014-04-28 16:47:08 -0700558 if (UNLIKELY(field_value.is_volatile)) {
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800559 obj->SetField32Volatile<false, kCheckTransaction>(
560 field_offset,
561 static_cast<uint32_t>(field_value.value));
Ian Rogersb0fa5dc2014-04-28 16:47:08 -0700562 } else {
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800563 obj->SetField32<false, kCheckTransaction>(
564 field_offset,
565 static_cast<uint32_t>(field_value.value));
Ian Rogersb0fa5dc2014-04-28 16:47:08 -0700566 }
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100567 break;
568 case k64Bits:
Ian Rogersb0fa5dc2014-04-28 16:47:08 -0700569 if (UNLIKELY(field_value.is_volatile)) {
570 obj->SetField64Volatile<false, kCheckTransaction>(field_offset, field_value.value);
571 } else {
572 obj->SetField64<false, kCheckTransaction>(field_offset, field_value.value);
573 }
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100574 break;
575 case kReference:
Ian Rogersb0fa5dc2014-04-28 16:47:08 -0700576 if (UNLIKELY(field_value.is_volatile)) {
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800577 obj->SetFieldObjectVolatile<false, kCheckTransaction>(
578 field_offset,
579 reinterpret_cast<mirror::Object*>(field_value.value));
Ian Rogersb0fa5dc2014-04-28 16:47:08 -0700580 } else {
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800581 obj->SetFieldObject<false, kCheckTransaction>(
582 field_offset,
583 reinterpret_cast<mirror::Object*>(field_value.value));
Ian Rogersb0fa5dc2014-04-28 16:47:08 -0700584 }
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100585 break;
586 default:
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700587 LOG(FATAL) << "Unknown value kind " << static_cast<int>(field_value.kind);
Elliott Hughesc1896c92018-11-29 11:33:18 -0800588 UNREACHABLE();
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100589 }
590}
591
Mathieu Chartierbb87e0f2015-04-03 11:21:55 -0700592void Transaction::ObjectLog::VisitRoots(RootVisitor* visitor) {
Mathieu Chartier5f257b12017-02-03 14:47:36 -0800593 for (auto& it : field_values_) {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100594 FieldValue& field_value = it.second;
595 if (field_value.kind == ObjectLog::kReference) {
Mathieu Chartierbb87e0f2015-04-03 11:21:55 -0700596 visitor->VisitRootIfNonNull(reinterpret_cast<mirror::Object**>(&field_value.value),
597 RootInfo(kRootUnknown));
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100598 }
599 }
600}
601
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800602void Transaction::InternStringLog::Undo(InternTable* intern_table) const {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100603 DCHECK(intern_table != nullptr);
604 switch (string_op_) {
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700605 case InternStringLog::kInsert: {
606 switch (string_kind_) {
607 case InternStringLog::kStrongString:
Mathieu Chartier9e868092016-10-31 14:58:04 -0700608 intern_table->RemoveStrongFromTransaction(str_.Read());
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700609 break;
610 case InternStringLog::kWeakString:
Mathieu Chartier9e868092016-10-31 14:58:04 -0700611 intern_table->RemoveWeakFromTransaction(str_.Read());
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700612 break;
613 default:
614 LOG(FATAL) << "Unknown interned string kind";
Elliott Hughesc1896c92018-11-29 11:33:18 -0800615 UNREACHABLE();
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100616 }
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700617 break;
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100618 }
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700619 case InternStringLog::kRemove: {
620 switch (string_kind_) {
621 case InternStringLog::kStrongString:
Mathieu Chartier9e868092016-10-31 14:58:04 -0700622 intern_table->InsertStrongFromTransaction(str_.Read());
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700623 break;
624 case InternStringLog::kWeakString:
Mathieu Chartier9e868092016-10-31 14:58:04 -0700625 intern_table->InsertWeakFromTransaction(str_.Read());
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700626 break;
627 default:
628 LOG(FATAL) << "Unknown interned string kind";
Elliott Hughesc1896c92018-11-29 11:33:18 -0800629 UNREACHABLE();
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700630 }
631 break;
632 }
633 default:
634 LOG(FATAL) << "Unknown interned string op";
Elliott Hughesc1896c92018-11-29 11:33:18 -0800635 UNREACHABLE();
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700636 }
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100637}
638
Mathieu Chartierbb87e0f2015-04-03 11:21:55 -0700639void Transaction::InternStringLog::VisitRoots(RootVisitor* visitor) {
Mathieu Chartier9e868092016-10-31 14:58:04 -0700640 str_.VisitRoot(visitor, RootInfo(kRootInternedString));
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100641}
642
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800643void Transaction::ResolveStringLog::Undo() const {
Mathieu Chartierbb816d62016-09-07 10:17:46 -0700644 dex_cache_.Read()->ClearString(string_idx_);
645}
646
Mathieu Chartier9e868092016-10-31 14:58:04 -0700647Transaction::ResolveStringLog::ResolveStringLog(ObjPtr<mirror::DexCache> dex_cache,
Andreas Gampe8a0128a2016-11-28 07:38:35 -0800648 dex::StringIndex string_idx)
Mathieu Chartierbb816d62016-09-07 10:17:46 -0700649 : dex_cache_(dex_cache),
650 string_idx_(string_idx) {
651 DCHECK(dex_cache != nullptr);
Andreas Gampe8a0128a2016-11-28 07:38:35 -0800652 DCHECK_LT(string_idx_.index_, dex_cache->GetDexFile()->NumStringIds());
Mathieu Chartierbb816d62016-09-07 10:17:46 -0700653}
654
655void Transaction::ResolveStringLog::VisitRoots(RootVisitor* visitor) {
656 dex_cache_.VisitRoot(visitor, RootInfo(kRootVMInternal));
657}
658
Vladimir Markoe9a4a602021-06-22 16:33:34 +0100659void Transaction::ResolveMethodTypeLog::Undo() const {
660 dex_cache_.Read()->ClearMethodType(proto_idx_);
661}
662
663Transaction::ResolveMethodTypeLog::ResolveMethodTypeLog(ObjPtr<mirror::DexCache> dex_cache,
664 dex::ProtoIndex proto_idx)
665 : dex_cache_(dex_cache),
666 proto_idx_(proto_idx) {
667 DCHECK(dex_cache != nullptr);
668 DCHECK_LT(proto_idx_.index_, dex_cache->GetDexFile()->NumProtoIds());
669}
670
671void Transaction::ResolveMethodTypeLog::VisitRoots(RootVisitor* visitor) {
672 dex_cache_.VisitRoot(visitor, RootInfo(kRootVMInternal));
673}
674
Mathieu Chartier9e868092016-10-31 14:58:04 -0700675Transaction::InternStringLog::InternStringLog(ObjPtr<mirror::String> s,
676 StringKind kind,
677 StringOp op)
678 : str_(s),
679 string_kind_(kind),
680 string_op_(op) {
681 DCHECK(s != nullptr);
682}
683
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100684void Transaction::ArrayLog::LogValue(size_t index, uint64_t value) {
Vladimir Markob6e67922021-07-06 15:53:07 +0100685 // Add a mapping if there is none yet.
686 array_values_.FindOrAdd(index, value);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100687}
688
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800689void Transaction::ArrayLog::Undo(mirror::Array* array) const {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100690 DCHECK(array != nullptr);
691 DCHECK(array->IsArrayInstance());
692 Primitive::Type type = array->GetClass()->GetComponentType()->GetPrimitiveType();
693 for (auto it : array_values_) {
694 UndoArrayWrite(array, type, it.first, it.second);
695 }
696}
697
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800698void Transaction::ArrayLog::UndoArrayWrite(mirror::Array* array,
699 Primitive::Type array_type,
700 size_t index,
701 uint64_t value) const {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100702 // TODO We may want to abort a transaction while still being in transaction mode. In this case,
703 // we'd need to disable the check.
Chang Xing605fe242017-07-20 15:57:21 -0700704 constexpr bool kCheckTransaction = false;
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100705 switch (array_type) {
706 case Primitive::kPrimBoolean:
Chang Xing605fe242017-07-20 15:57:21 -0700707 array->AsBooleanArray()->SetWithoutChecks<false, kCheckTransaction>(
708 index, static_cast<uint8_t>(value));
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100709 break;
710 case Primitive::kPrimByte:
Chang Xing605fe242017-07-20 15:57:21 -0700711 array->AsByteArray()->SetWithoutChecks<false, kCheckTransaction>(
712 index, static_cast<int8_t>(value));
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100713 break;
714 case Primitive::kPrimChar:
Chang Xing605fe242017-07-20 15:57:21 -0700715 array->AsCharArray()->SetWithoutChecks<false, kCheckTransaction>(
716 index, static_cast<uint16_t>(value));
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100717 break;
718 case Primitive::kPrimShort:
Chang Xing605fe242017-07-20 15:57:21 -0700719 array->AsShortArray()->SetWithoutChecks<false, kCheckTransaction>(
720 index, static_cast<int16_t>(value));
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100721 break;
722 case Primitive::kPrimInt:
Chang Xing605fe242017-07-20 15:57:21 -0700723 array->AsIntArray()->SetWithoutChecks<false, kCheckTransaction>(
724 index, static_cast<int32_t>(value));
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100725 break;
726 case Primitive::kPrimFloat:
Chang Xing605fe242017-07-20 15:57:21 -0700727 array->AsFloatArray()->SetWithoutChecks<false, kCheckTransaction>(
728 index, static_cast<float>(value));
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100729 break;
730 case Primitive::kPrimLong:
Chang Xing605fe242017-07-20 15:57:21 -0700731 array->AsLongArray()->SetWithoutChecks<false, kCheckTransaction>(
732 index, static_cast<int64_t>(value));
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100733 break;
734 case Primitive::kPrimDouble:
Chang Xing605fe242017-07-20 15:57:21 -0700735 array->AsDoubleArray()->SetWithoutChecks<false, kCheckTransaction>(
736 index, static_cast<double>(value));
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100737 break;
Sebastien Hertzee1d79a2014-02-21 15:46:30 +0100738 case Primitive::kPrimNot:
739 LOG(FATAL) << "ObjectArray should be treated as Object";
Elliott Hughesc1896c92018-11-29 11:33:18 -0800740 UNREACHABLE();
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100741 default:
742 LOG(FATAL) << "Unsupported type " << array_type;
Elliott Hughesc1896c92018-11-29 11:33:18 -0800743 UNREACHABLE();
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100744 }
745}
746
Vladimir Markob68bb7a2020-03-17 10:55:25 +0000747Transaction* ScopedAssertNoNewTransactionRecords::InstallAssertion(const char* reason) {
748 Transaction* transaction = nullptr;
749 if (kIsDebugBuild && Runtime::Current()->IsActiveTransaction()) {
Vladimir Markob6e67922021-07-06 15:53:07 +0100750 transaction = Runtime::Current()->GetTransaction();
Vladimir Markob68bb7a2020-03-17 10:55:25 +0000751 if (transaction != nullptr) {
Vladimir Markob68bb7a2020-03-17 10:55:25 +0000752 CHECK(transaction->assert_no_new_records_reason_ == nullptr)
753 << "old: " << transaction->assert_no_new_records_reason_ << " new: " << reason;
754 transaction->assert_no_new_records_reason_ = reason;
755 }
756 }
757 return transaction;
758}
759
760void ScopedAssertNoNewTransactionRecords::RemoveAssertion(Transaction* transaction) {
761 if (kIsDebugBuild) {
Vladimir Markob6e67922021-07-06 15:53:07 +0100762 CHECK(Runtime::Current()->GetTransaction() == transaction);
Vladimir Markob68bb7a2020-03-17 10:55:25 +0000763 CHECK(transaction->assert_no_new_records_reason_ != nullptr);
764 transaction->assert_no_new_records_reason_ = nullptr;
765 }
766}
767
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100768} // namespace art