blob: c534a423b84dbff0866aa894181d2d146872043c [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
Andreas Gampe88dbad32018-06-26 19:54:12 -070021#include "base/mutex-inl.h"
Andreas Gampe8cf9cb32017-07-19 09:28:38 -070022#include "base/stl_util.h"
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +010023#include "gc/accounting/card_table-inl.h"
Andreas Gampe508fdf32017-06-05 16:42:13 -070024#include "gc_root-inl.h"
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +010025#include "intern_table.h"
Mathieu Chartiere401d142015-04-22 13:56:20 -070026#include "mirror/class-inl.h"
Andreas Gampe508fdf32017-06-05 16:42:13 -070027#include "mirror/dex_cache-inl.h"
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +010028#include "mirror/object-inl.h"
29#include "mirror/object_array-inl.h"
30
31#include <list>
32
33namespace art {
34
35// TODO: remove (only used for debugging purpose).
36static constexpr bool kEnableTransactionStats = false;
37
Sebastien Hertz1c80bec2015-02-03 11:58:06 +010038Transaction::Transaction()
Chang Xing5a906fc2017-07-26 15:01:16 -070039 : log_lock_("transaction log lock", kTransactionLogLock),
40 aborted_(false),
Chang Xing605fe242017-07-20 15:57:21 -070041 rolling_back_(false),
Chang Xing5a906fc2017-07-26 15:01:16 -070042 strict_(false) {
Mathieu Chartiere5f13e52015-02-24 09:37:21 -080043 CHECK(Runtime::Current()->IsAotCompiler());
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +010044}
45
Chang Xing5a906fc2017-07-26 15:01:16 -070046Transaction::Transaction(bool strict, mirror::Class* root) : Transaction() {
47 strict_ = strict;
Chang Xingcade5c32017-07-20 17:56:26 -070048 root_ = root;
49}
50
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +010051Transaction::~Transaction() {
52 if (kEnableTransactionStats) {
53 MutexLock mu(Thread::Current(), log_lock_);
54 size_t objects_count = object_logs_.size();
55 size_t field_values_count = 0;
Mathieu Chartier38e954c2017-02-03 16:06:35 -080056 for (const auto& it : object_logs_) {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +010057 field_values_count += it.second.Size();
58 }
59 size_t array_count = array_logs_.size();
60 size_t array_values_count = 0;
Mathieu Chartier38e954c2017-02-03 16:06:35 -080061 for (const auto& it : array_logs_) {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +010062 array_values_count += it.second.Size();
63 }
Mathieu Chartierbb816d62016-09-07 10:17:46 -070064 size_t intern_string_count = intern_string_logs_.size();
65 size_t resolve_string_count = resolve_string_logs_.size();
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +010066 LOG(INFO) << "Transaction::~Transaction"
67 << ": objects_count=" << objects_count
68 << ", field_values_count=" << field_values_count
69 << ", array_count=" << array_count
70 << ", array_values_count=" << array_values_count
Mathieu Chartierbb816d62016-09-07 10:17:46 -070071 << ", intern_string_count=" << intern_string_count
72 << ", resolve_string_count=" << resolve_string_count;
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +010073 }
74}
75
Sebastien Hertz1c80bec2015-02-03 11:58:06 +010076void Transaction::Abort(const std::string& abort_message) {
77 MutexLock mu(Thread::Current(), log_lock_);
Sebastien Hertz2fd7e692015-04-02 11:11:19 +020078 // We may abort more than once if the exception thrown at the time of the
79 // previous abort has been caught during execution of a class initializer.
Sebastien Hertz1c80bec2015-02-03 11:58:06 +010080 // We just keep the message of the first abort because it will cause the
81 // transaction to be rolled back anyway.
82 if (!aborted_) {
83 aborted_ = true;
84 abort_message_ = abort_message;
85 }
86}
87
Sebastien Hertzb81e1cd2015-04-28 12:31:41 +020088void Transaction::ThrowAbortError(Thread* self, const std::string* abort_message) {
89 const bool rethrow = (abort_message == nullptr);
Sebastien Hertzbd9cf9f2015-03-03 12:16:13 +010090 if (kIsDebugBuild && rethrow) {
Sebastien Hertz2fd7e692015-04-02 11:11:19 +020091 CHECK(IsAborted()) << "Rethrow " << Transaction::kAbortExceptionDescriptor
92 << " while transaction is not aborted";
Sebastien Hertzbd9cf9f2015-03-03 12:16:13 +010093 }
Sebastien Hertzb81e1cd2015-04-28 12:31:41 +020094 if (rethrow) {
95 // Rethrow an exception with the earlier abort message stored in the transaction.
96 self->ThrowNewWrappedException(Transaction::kAbortExceptionSignature,
97 GetAbortMessage().c_str());
98 } else {
99 // Throw an exception with the given abort message.
100 self->ThrowNewWrappedException(Transaction::kAbortExceptionSignature,
101 abort_message->c_str());
102 }
Sebastien Hertz1c80bec2015-02-03 11:58:06 +0100103}
104
105bool Transaction::IsAborted() {
106 MutexLock mu(Thread::Current(), log_lock_);
107 return aborted_;
108}
109
Chang Xing605fe242017-07-20 15:57:21 -0700110bool Transaction::IsRollingBack() {
111 return rolling_back_;
112}
113
Chang Xing5a906fc2017-07-26 15:01:16 -0700114bool Transaction::IsStrict() {
115 MutexLock mu(Thread::Current(), log_lock_);
116 return strict_;
117}
118
Sebastien Hertz1c80bec2015-02-03 11:58:06 +0100119const std::string& Transaction::GetAbortMessage() {
120 MutexLock mu(Thread::Current(), log_lock_);
121 return abort_message_;
122}
123
Chang Xingbd208d82017-07-12 14:53:17 -0700124bool Transaction::WriteConstraint(mirror::Object* obj, ArtField* field) {
125 MutexLock mu(Thread::Current(), log_lock_);
126 if (strict_ // no constraint for boot image
127 && field->IsStatic() // no constraint instance updating
128 && obj != root_) { // modifying other classes' static field, fail
129 return true;
130 }
131 return false;
132}
133
134bool Transaction::ReadConstraint(mirror::Object* obj, ArtField* field) {
135 DCHECK(field->IsStatic());
136 DCHECK(obj->IsClass());
137 MutexLock mu(Thread::Current(), log_lock_);
138 if (!strict_ || // no constraint for boot image
139 obj == root_) { // self-updating, pass
140 return false;
141 }
142 return true;
143}
144
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800145void Transaction::RecordWriteFieldBoolean(mirror::Object* obj,
146 MemberOffset field_offset,
147 uint8_t value,
148 bool is_volatile) {
Fred Shih37f05ef2014-07-16 18:38:08 -0700149 DCHECK(obj != nullptr);
150 MutexLock mu(Thread::Current(), log_lock_);
151 ObjectLog& object_log = object_logs_[obj];
152 object_log.LogBooleanValue(field_offset, value, is_volatile);
153}
154
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800155void Transaction::RecordWriteFieldByte(mirror::Object* obj,
156 MemberOffset field_offset,
157 int8_t value,
158 bool is_volatile) {
Fred Shih37f05ef2014-07-16 18:38:08 -0700159 DCHECK(obj != nullptr);
160 MutexLock mu(Thread::Current(), log_lock_);
161 ObjectLog& object_log = object_logs_[obj];
162 object_log.LogByteValue(field_offset, value, is_volatile);
163}
164
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800165void Transaction::RecordWriteFieldChar(mirror::Object* obj,
166 MemberOffset field_offset,
167 uint16_t value,
168 bool is_volatile) {
Fred Shih37f05ef2014-07-16 18:38:08 -0700169 DCHECK(obj != nullptr);
170 MutexLock mu(Thread::Current(), log_lock_);
171 ObjectLog& object_log = object_logs_[obj];
172 object_log.LogCharValue(field_offset, value, is_volatile);
173}
174
175
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800176void Transaction::RecordWriteFieldShort(mirror::Object* obj,
177 MemberOffset field_offset,
178 int16_t value,
179 bool is_volatile) {
Fred Shih37f05ef2014-07-16 18:38:08 -0700180 DCHECK(obj != nullptr);
181 MutexLock mu(Thread::Current(), log_lock_);
182 ObjectLog& object_log = object_logs_[obj];
183 object_log.LogShortValue(field_offset, value, is_volatile);
184}
185
186
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800187void Transaction::RecordWriteField32(mirror::Object* obj,
188 MemberOffset field_offset,
189 uint32_t value,
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100190 bool is_volatile) {
191 DCHECK(obj != nullptr);
192 MutexLock mu(Thread::Current(), log_lock_);
193 ObjectLog& object_log = object_logs_[obj];
194 object_log.Log32BitsValue(field_offset, value, is_volatile);
195}
196
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800197void Transaction::RecordWriteField64(mirror::Object* obj,
198 MemberOffset field_offset,
199 uint64_t value,
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100200 bool is_volatile) {
201 DCHECK(obj != nullptr);
202 MutexLock mu(Thread::Current(), log_lock_);
203 ObjectLog& object_log = object_logs_[obj];
204 object_log.Log64BitsValue(field_offset, value, is_volatile);
205}
206
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800207void Transaction::RecordWriteFieldReference(mirror::Object* obj,
208 MemberOffset field_offset,
209 mirror::Object* value,
210 bool is_volatile) {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100211 DCHECK(obj != nullptr);
212 MutexLock mu(Thread::Current(), log_lock_);
213 ObjectLog& object_log = object_logs_[obj];
214 object_log.LogReferenceValue(field_offset, value, is_volatile);
215}
216
217void Transaction::RecordWriteArray(mirror::Array* array, size_t index, uint64_t value) {
218 DCHECK(array != nullptr);
219 DCHECK(array->IsArrayInstance());
Sebastien Hertzee1d79a2014-02-21 15:46:30 +0100220 DCHECK(!array->IsObjectArray());
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100221 MutexLock mu(Thread::Current(), log_lock_);
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800222 auto it = array_logs_.find(array);
223 if (it == array_logs_.end()) {
224 ArrayLog log;
225 it = array_logs_.emplace(array, std::move(log)).first;
226 }
227 it->second.LogValue(index, value);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100228}
229
Andreas Gampe8a0128a2016-11-28 07:38:35 -0800230void Transaction::RecordResolveString(ObjPtr<mirror::DexCache> dex_cache,
231 dex::StringIndex string_idx) {
Mathieu Chartierbb816d62016-09-07 10:17:46 -0700232 DCHECK(dex_cache != nullptr);
Andreas Gampe8a0128a2016-11-28 07:38:35 -0800233 DCHECK_LT(string_idx.index_, dex_cache->GetDexFile()->NumStringIds());
Mathieu Chartierbb816d62016-09-07 10:17:46 -0700234 MutexLock mu(Thread::Current(), log_lock_);
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800235 resolve_string_logs_.emplace_back(dex_cache, string_idx);
Mathieu Chartierbb816d62016-09-07 10:17:46 -0700236}
237
Mathieu Chartier9e868092016-10-31 14:58:04 -0700238void Transaction::RecordStrongStringInsertion(ObjPtr<mirror::String> s) {
Mathieu Chartiercdfd39f2014-08-29 18:16:58 -0700239 InternStringLog log(s, InternStringLog::kStrongString, InternStringLog::kInsert);
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800240 LogInternedString(std::move(log));
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100241}
242
Mathieu Chartier9e868092016-10-31 14:58:04 -0700243void Transaction::RecordWeakStringInsertion(ObjPtr<mirror::String> s) {
Mathieu Chartiercdfd39f2014-08-29 18:16:58 -0700244 InternStringLog log(s, InternStringLog::kWeakString, InternStringLog::kInsert);
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800245 LogInternedString(std::move(log));
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100246}
247
Mathieu Chartier9e868092016-10-31 14:58:04 -0700248void Transaction::RecordStrongStringRemoval(ObjPtr<mirror::String> s) {
Mathieu Chartiercdfd39f2014-08-29 18:16:58 -0700249 InternStringLog log(s, InternStringLog::kStrongString, InternStringLog::kRemove);
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800250 LogInternedString(std::move(log));
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100251}
252
Mathieu Chartier9e868092016-10-31 14:58:04 -0700253void Transaction::RecordWeakStringRemoval(ObjPtr<mirror::String> s) {
Mathieu Chartiercdfd39f2014-08-29 18:16:58 -0700254 InternStringLog log(s, InternStringLog::kWeakString, InternStringLog::kRemove);
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800255 LogInternedString(std::move(log));
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100256}
257
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800258void Transaction::LogInternedString(InternStringLog&& log) {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100259 Locks::intern_table_lock_->AssertExclusiveHeld(Thread::Current());
260 MutexLock mu(Thread::Current(), log_lock_);
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800261 intern_string_logs_.push_front(std::move(log));
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100262}
263
Sebastien Hertz1c80bec2015-02-03 11:58:06 +0100264void Transaction::Rollback() {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100265 Thread* self = Thread::Current();
266 self->AssertNoPendingException();
267 MutexLock mu1(self, *Locks::intern_table_lock_);
268 MutexLock mu2(self, log_lock_);
Chang Xing605fe242017-07-20 15:57:21 -0700269 rolling_back_ = true;
270 CHECK(!Runtime::Current()->IsActiveTransaction());
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100271 UndoObjectModifications();
272 UndoArrayModifications();
273 UndoInternStringTableModifications();
Mathieu Chartierbb816d62016-09-07 10:17:46 -0700274 UndoResolveStringModifications();
Chang Xing605fe242017-07-20 15:57:21 -0700275 rolling_back_ = false;
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100276}
277
278void Transaction::UndoObjectModifications() {
279 // TODO we may not need to restore objects allocated during this transaction. Or we could directly
280 // remove them from the heap.
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800281 for (const auto& it : object_logs_) {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100282 it.second.Undo(it.first);
283 }
284 object_logs_.clear();
285}
286
287void Transaction::UndoArrayModifications() {
288 // TODO we may not need to restore array allocated during this transaction. Or we could directly
289 // remove them from the heap.
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800290 for (const auto& it : array_logs_) {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100291 it.second.Undo(it.first);
292 }
293 array_logs_.clear();
294}
295
296void Transaction::UndoInternStringTableModifications() {
297 InternTable* const intern_table = Runtime::Current()->GetInternTable();
298 // We want to undo each operation from the most recent to the oldest. List has been filled so the
299 // most recent operation is at list begin so just have to iterate over it.
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800300 for (const InternStringLog& string_log : intern_string_logs_) {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100301 string_log.Undo(intern_table);
302 }
303 intern_string_logs_.clear();
304}
305
Mathieu Chartierbb816d62016-09-07 10:17:46 -0700306void Transaction::UndoResolveStringModifications() {
307 for (ResolveStringLog& string_log : resolve_string_logs_) {
308 string_log.Undo();
309 }
310 resolve_string_logs_.clear();
311}
312
Mathieu Chartierbb87e0f2015-04-03 11:21:55 -0700313void Transaction::VisitRoots(RootVisitor* visitor) {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100314 MutexLock mu(Thread::Current(), log_lock_);
Chang Xingcade5c32017-07-20 17:56:26 -0700315 visitor->VisitRoot(reinterpret_cast<mirror::Object**>(&root_), RootInfo(kRootUnknown));
Mathieu Chartierbb87e0f2015-04-03 11:21:55 -0700316 VisitObjectLogs(visitor);
317 VisitArrayLogs(visitor);
Mathieu Chartierbb816d62016-09-07 10:17:46 -0700318 VisitInternStringLogs(visitor);
319 VisitResolveStringLogs(visitor);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100320}
321
Mathieu Chartierbb87e0f2015-04-03 11:21:55 -0700322void Transaction::VisitObjectLogs(RootVisitor* visitor) {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100323 // List of moving roots.
Andreas Gampec55bb392018-09-21 00:02:02 +0000324 using ObjectPair = std::pair<mirror::Object*, mirror::Object*>;
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100325 std::list<ObjectPair> moving_roots;
326
327 // Visit roots.
Mathieu Chartier5f257b12017-02-03 14:47:36 -0800328 for (auto& it : object_logs_) {
Mathieu Chartierbb87e0f2015-04-03 11:21:55 -0700329 it.second.VisitRoots(visitor);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100330 mirror::Object* old_root = it.first;
Mathieu Chartier815873e2014-02-13 18:02:13 -0800331 mirror::Object* new_root = old_root;
Mathieu Chartierbb87e0f2015-04-03 11:21:55 -0700332 visitor->VisitRoot(&new_root, RootInfo(kRootUnknown));
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100333 if (new_root != old_root) {
334 moving_roots.push_back(std::make_pair(old_root, new_root));
335 }
336 }
337
338 // Update object logs with moving roots.
339 for (const ObjectPair& pair : moving_roots) {
340 mirror::Object* old_root = pair.first;
341 mirror::Object* new_root = pair.second;
342 auto old_root_it = object_logs_.find(old_root);
343 CHECK(old_root_it != object_logs_.end());
344 CHECK(object_logs_.find(new_root) == object_logs_.end());
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800345 object_logs_.emplace(new_root, std::move(old_root_it->second));
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100346 object_logs_.erase(old_root_it);
347 }
348}
349
Mathieu Chartierbb87e0f2015-04-03 11:21:55 -0700350void Transaction::VisitArrayLogs(RootVisitor* visitor) {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100351 // List of moving roots.
Andreas Gampec55bb392018-09-21 00:02:02 +0000352 using ArrayPair = std::pair<mirror::Array*, mirror::Array*>;
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100353 std::list<ArrayPair> moving_roots;
354
Mathieu Chartier5f257b12017-02-03 14:47:36 -0800355 for (auto& it : array_logs_) {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100356 mirror::Array* old_root = it.first;
Sebastien Hertzee1d79a2014-02-21 15:46:30 +0100357 CHECK(!old_root->IsObjectArray());
Mathieu Chartier815873e2014-02-13 18:02:13 -0800358 mirror::Array* new_root = old_root;
Mathieu Chartierbb87e0f2015-04-03 11:21:55 -0700359 visitor->VisitRoot(reinterpret_cast<mirror::Object**>(&new_root), RootInfo(kRootUnknown));
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100360 if (new_root != old_root) {
361 moving_roots.push_back(std::make_pair(old_root, new_root));
362 }
363 }
364
365 // Update array logs with moving roots.
366 for (const ArrayPair& pair : moving_roots) {
367 mirror::Array* old_root = pair.first;
368 mirror::Array* new_root = pair.second;
369 auto old_root_it = array_logs_.find(old_root);
370 CHECK(old_root_it != array_logs_.end());
371 CHECK(array_logs_.find(new_root) == array_logs_.end());
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800372 array_logs_.emplace(new_root, std::move(old_root_it->second));
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100373 array_logs_.erase(old_root_it);
374 }
375}
376
Mathieu Chartierbb816d62016-09-07 10:17:46 -0700377void Transaction::VisitInternStringLogs(RootVisitor* visitor) {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100378 for (InternStringLog& log : intern_string_logs_) {
Mathieu Chartierbb87e0f2015-04-03 11:21:55 -0700379 log.VisitRoots(visitor);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100380 }
381}
382
Mathieu Chartierbb816d62016-09-07 10:17:46 -0700383void Transaction::VisitResolveStringLogs(RootVisitor* visitor) {
384 for (ResolveStringLog& log : resolve_string_logs_) {
385 log.VisitRoots(visitor);
386 }
387}
388
Fred Shih37f05ef2014-07-16 18:38:08 -0700389void Transaction::ObjectLog::LogBooleanValue(MemberOffset offset, uint8_t value, bool is_volatile) {
390 LogValue(ObjectLog::kBoolean, offset, value, is_volatile);
391}
392
393void Transaction::ObjectLog::LogByteValue(MemberOffset offset, int8_t value, bool is_volatile) {
394 LogValue(ObjectLog::kByte, offset, value, is_volatile);
395}
396
397void Transaction::ObjectLog::LogCharValue(MemberOffset offset, uint16_t value, bool is_volatile) {
398 LogValue(ObjectLog::kChar, offset, value, is_volatile);
399}
400
401void Transaction::ObjectLog::LogShortValue(MemberOffset offset, int16_t value, bool is_volatile) {
402 LogValue(ObjectLog::kShort, offset, value, is_volatile);
403}
404
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100405void Transaction::ObjectLog::Log32BitsValue(MemberOffset offset, uint32_t value, bool is_volatile) {
Fred Shih37f05ef2014-07-16 18:38:08 -0700406 LogValue(ObjectLog::k32Bits, offset, value, is_volatile);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100407}
408
409void Transaction::ObjectLog::Log64BitsValue(MemberOffset offset, uint64_t value, bool is_volatile) {
Fred Shih37f05ef2014-07-16 18:38:08 -0700410 LogValue(ObjectLog::k64Bits, offset, value, is_volatile);
411}
412
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800413void Transaction::ObjectLog::LogReferenceValue(MemberOffset offset,
414 mirror::Object* obj,
415 bool is_volatile) {
Fred Shih37f05ef2014-07-16 18:38:08 -0700416 LogValue(ObjectLog::kReference, offset, reinterpret_cast<uintptr_t>(obj), is_volatile);
417}
418
419void Transaction::ObjectLog::LogValue(ObjectLog::FieldValueKind kind,
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800420 MemberOffset offset,
421 uint64_t value,
422 bool is_volatile) {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100423 auto it = field_values_.find(offset.Uint32Value());
424 if (it == field_values_.end()) {
425 ObjectLog::FieldValue field_value;
426 field_value.value = value;
427 field_value.is_volatile = is_volatile;
Fred Shih37f05ef2014-07-16 18:38:08 -0700428 field_value.kind = kind;
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800429 field_values_.emplace(offset.Uint32Value(), std::move(field_value));
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100430 }
431}
432
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800433void Transaction::ObjectLog::Undo(mirror::Object* obj) const {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100434 for (auto& it : field_values_) {
435 // Garbage collector needs to access object's class and array's length. So we don't rollback
436 // these values.
437 MemberOffset field_offset(it.first);
438 if (field_offset.Uint32Value() == mirror::Class::ClassOffset().Uint32Value()) {
439 // Skip Object::class field.
440 continue;
441 }
442 if (obj->IsArrayInstance() &&
443 field_offset.Uint32Value() == mirror::Array::LengthOffset().Uint32Value()) {
444 // Skip Array::length field.
445 continue;
446 }
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800447 const FieldValue& field_value = it.second;
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100448 UndoFieldWrite(obj, field_offset, field_value);
449 }
450}
451
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800452void Transaction::ObjectLog::UndoFieldWrite(mirror::Object* obj,
453 MemberOffset field_offset,
454 const FieldValue& field_value) const {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100455 // TODO We may want to abort a transaction while still being in transaction mode. In this case,
456 // we'd need to disable the check.
Chang Xing605fe242017-07-20 15:57:21 -0700457 constexpr bool kCheckTransaction = false;
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100458 switch (field_value.kind) {
Fred Shih37f05ef2014-07-16 18:38:08 -0700459 case kBoolean:
460 if (UNLIKELY(field_value.is_volatile)) {
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800461 obj->SetFieldBooleanVolatile<false, kCheckTransaction>(
462 field_offset,
Andreas Gampe7c5acbb2018-09-20 13:54:52 -0700463 field_value.value);
Fred Shih37f05ef2014-07-16 18:38:08 -0700464 } else {
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800465 obj->SetFieldBoolean<false, kCheckTransaction>(
466 field_offset,
Andreas Gampe7c5acbb2018-09-20 13:54:52 -0700467 field_value.value);
Fred Shih37f05ef2014-07-16 18:38:08 -0700468 }
469 break;
470 case kByte:
471 if (UNLIKELY(field_value.is_volatile)) {
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800472 obj->SetFieldByteVolatile<false, kCheckTransaction>(
473 field_offset,
474 static_cast<int8_t>(field_value.value));
Fred Shih37f05ef2014-07-16 18:38:08 -0700475 } else {
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800476 obj->SetFieldByte<false, kCheckTransaction>(
477 field_offset,
478 static_cast<int8_t>(field_value.value));
Fred Shih37f05ef2014-07-16 18:38:08 -0700479 }
480 break;
481 case kChar:
482 if (UNLIKELY(field_value.is_volatile)) {
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800483 obj->SetFieldCharVolatile<false, kCheckTransaction>(
484 field_offset,
485 static_cast<uint16_t>(field_value.value));
Fred Shih37f05ef2014-07-16 18:38:08 -0700486 } else {
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800487 obj->SetFieldChar<false, kCheckTransaction>(
488 field_offset,
489 static_cast<uint16_t>(field_value.value));
Fred Shih37f05ef2014-07-16 18:38:08 -0700490 }
491 break;
492 case kShort:
493 if (UNLIKELY(field_value.is_volatile)) {
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800494 obj->SetFieldShortVolatile<false, kCheckTransaction>(
495 field_offset,
496 static_cast<int16_t>(field_value.value));
Fred Shih37f05ef2014-07-16 18:38:08 -0700497 } else {
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800498 obj->SetFieldShort<false, kCheckTransaction>(
499 field_offset,
500 static_cast<int16_t>(field_value.value));
Fred Shih37f05ef2014-07-16 18:38:08 -0700501 }
502 break;
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100503 case k32Bits:
Ian Rogersb0fa5dc2014-04-28 16:47:08 -0700504 if (UNLIKELY(field_value.is_volatile)) {
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800505 obj->SetField32Volatile<false, kCheckTransaction>(
506 field_offset,
507 static_cast<uint32_t>(field_value.value));
Ian Rogersb0fa5dc2014-04-28 16:47:08 -0700508 } else {
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800509 obj->SetField32<false, kCheckTransaction>(
510 field_offset,
511 static_cast<uint32_t>(field_value.value));
Ian Rogersb0fa5dc2014-04-28 16:47:08 -0700512 }
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100513 break;
514 case k64Bits:
Ian Rogersb0fa5dc2014-04-28 16:47:08 -0700515 if (UNLIKELY(field_value.is_volatile)) {
516 obj->SetField64Volatile<false, kCheckTransaction>(field_offset, field_value.value);
517 } else {
518 obj->SetField64<false, kCheckTransaction>(field_offset, field_value.value);
519 }
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100520 break;
521 case kReference:
Ian Rogersb0fa5dc2014-04-28 16:47:08 -0700522 if (UNLIKELY(field_value.is_volatile)) {
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800523 obj->SetFieldObjectVolatile<false, kCheckTransaction>(
524 field_offset,
525 reinterpret_cast<mirror::Object*>(field_value.value));
Ian Rogersb0fa5dc2014-04-28 16:47:08 -0700526 } else {
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800527 obj->SetFieldObject<false, kCheckTransaction>(
528 field_offset,
529 reinterpret_cast<mirror::Object*>(field_value.value));
Ian Rogersb0fa5dc2014-04-28 16:47:08 -0700530 }
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100531 break;
532 default:
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700533 LOG(FATAL) << "Unknown value kind " << static_cast<int>(field_value.kind);
Elliott Hughesc1896c92018-11-29 11:33:18 -0800534 UNREACHABLE();
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100535 }
536}
537
Mathieu Chartierbb87e0f2015-04-03 11:21:55 -0700538void Transaction::ObjectLog::VisitRoots(RootVisitor* visitor) {
Mathieu Chartier5f257b12017-02-03 14:47:36 -0800539 for (auto& it : field_values_) {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100540 FieldValue& field_value = it.second;
541 if (field_value.kind == ObjectLog::kReference) {
Mathieu Chartierbb87e0f2015-04-03 11:21:55 -0700542 visitor->VisitRootIfNonNull(reinterpret_cast<mirror::Object**>(&field_value.value),
543 RootInfo(kRootUnknown));
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100544 }
545 }
546}
547
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800548void Transaction::InternStringLog::Undo(InternTable* intern_table) const {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100549 DCHECK(intern_table != nullptr);
550 switch (string_op_) {
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700551 case InternStringLog::kInsert: {
552 switch (string_kind_) {
553 case InternStringLog::kStrongString:
Mathieu Chartier9e868092016-10-31 14:58:04 -0700554 intern_table->RemoveStrongFromTransaction(str_.Read());
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700555 break;
556 case InternStringLog::kWeakString:
Mathieu Chartier9e868092016-10-31 14:58:04 -0700557 intern_table->RemoveWeakFromTransaction(str_.Read());
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700558 break;
559 default:
560 LOG(FATAL) << "Unknown interned string kind";
Elliott Hughesc1896c92018-11-29 11:33:18 -0800561 UNREACHABLE();
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100562 }
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700563 break;
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100564 }
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700565 case InternStringLog::kRemove: {
566 switch (string_kind_) {
567 case InternStringLog::kStrongString:
Mathieu Chartier9e868092016-10-31 14:58:04 -0700568 intern_table->InsertStrongFromTransaction(str_.Read());
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700569 break;
570 case InternStringLog::kWeakString:
Mathieu Chartier9e868092016-10-31 14:58:04 -0700571 intern_table->InsertWeakFromTransaction(str_.Read());
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700572 break;
573 default:
574 LOG(FATAL) << "Unknown interned string kind";
Elliott Hughesc1896c92018-11-29 11:33:18 -0800575 UNREACHABLE();
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700576 }
577 break;
578 }
579 default:
580 LOG(FATAL) << "Unknown interned string op";
Elliott Hughesc1896c92018-11-29 11:33:18 -0800581 UNREACHABLE();
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700582 }
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100583}
584
Mathieu Chartierbb87e0f2015-04-03 11:21:55 -0700585void Transaction::InternStringLog::VisitRoots(RootVisitor* visitor) {
Mathieu Chartier9e868092016-10-31 14:58:04 -0700586 str_.VisitRoot(visitor, RootInfo(kRootInternedString));
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100587}
588
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800589void Transaction::ResolveStringLog::Undo() const {
Mathieu Chartierbb816d62016-09-07 10:17:46 -0700590 dex_cache_.Read()->ClearString(string_idx_);
591}
592
Mathieu Chartier9e868092016-10-31 14:58:04 -0700593Transaction::ResolveStringLog::ResolveStringLog(ObjPtr<mirror::DexCache> dex_cache,
Andreas Gampe8a0128a2016-11-28 07:38:35 -0800594 dex::StringIndex string_idx)
Mathieu Chartierbb816d62016-09-07 10:17:46 -0700595 : dex_cache_(dex_cache),
596 string_idx_(string_idx) {
597 DCHECK(dex_cache != nullptr);
Andreas Gampe8a0128a2016-11-28 07:38:35 -0800598 DCHECK_LT(string_idx_.index_, dex_cache->GetDexFile()->NumStringIds());
Mathieu Chartierbb816d62016-09-07 10:17:46 -0700599}
600
601void Transaction::ResolveStringLog::VisitRoots(RootVisitor* visitor) {
602 dex_cache_.VisitRoot(visitor, RootInfo(kRootVMInternal));
603}
604
Mathieu Chartier9e868092016-10-31 14:58:04 -0700605Transaction::InternStringLog::InternStringLog(ObjPtr<mirror::String> s,
606 StringKind kind,
607 StringOp op)
608 : str_(s),
609 string_kind_(kind),
610 string_op_(op) {
611 DCHECK(s != nullptr);
612}
613
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100614void Transaction::ArrayLog::LogValue(size_t index, uint64_t value) {
615 auto it = array_values_.find(index);
616 if (it == array_values_.end()) {
617 array_values_.insert(std::make_pair(index, value));
618 }
619}
620
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800621void Transaction::ArrayLog::Undo(mirror::Array* array) const {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100622 DCHECK(array != nullptr);
623 DCHECK(array->IsArrayInstance());
624 Primitive::Type type = array->GetClass()->GetComponentType()->GetPrimitiveType();
625 for (auto it : array_values_) {
626 UndoArrayWrite(array, type, it.first, it.second);
627 }
628}
629
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800630void Transaction::ArrayLog::UndoArrayWrite(mirror::Array* array,
631 Primitive::Type array_type,
632 size_t index,
633 uint64_t value) const {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100634 // TODO We may want to abort a transaction while still being in transaction mode. In this case,
635 // we'd need to disable the check.
Chang Xing605fe242017-07-20 15:57:21 -0700636 constexpr bool kCheckTransaction = false;
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100637 switch (array_type) {
638 case Primitive::kPrimBoolean:
Chang Xing605fe242017-07-20 15:57:21 -0700639 array->AsBooleanArray()->SetWithoutChecks<false, kCheckTransaction>(
640 index, static_cast<uint8_t>(value));
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100641 break;
642 case Primitive::kPrimByte:
Chang Xing605fe242017-07-20 15:57:21 -0700643 array->AsByteArray()->SetWithoutChecks<false, kCheckTransaction>(
644 index, static_cast<int8_t>(value));
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100645 break;
646 case Primitive::kPrimChar:
Chang Xing605fe242017-07-20 15:57:21 -0700647 array->AsCharArray()->SetWithoutChecks<false, kCheckTransaction>(
648 index, static_cast<uint16_t>(value));
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100649 break;
650 case Primitive::kPrimShort:
Chang Xing605fe242017-07-20 15:57:21 -0700651 array->AsShortArray()->SetWithoutChecks<false, kCheckTransaction>(
652 index, static_cast<int16_t>(value));
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100653 break;
654 case Primitive::kPrimInt:
Chang Xing605fe242017-07-20 15:57:21 -0700655 array->AsIntArray()->SetWithoutChecks<false, kCheckTransaction>(
656 index, static_cast<int32_t>(value));
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100657 break;
658 case Primitive::kPrimFloat:
Chang Xing605fe242017-07-20 15:57:21 -0700659 array->AsFloatArray()->SetWithoutChecks<false, kCheckTransaction>(
660 index, static_cast<float>(value));
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100661 break;
662 case Primitive::kPrimLong:
Chang Xing605fe242017-07-20 15:57:21 -0700663 array->AsLongArray()->SetWithoutChecks<false, kCheckTransaction>(
664 index, static_cast<int64_t>(value));
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100665 break;
666 case Primitive::kPrimDouble:
Chang Xing605fe242017-07-20 15:57:21 -0700667 array->AsDoubleArray()->SetWithoutChecks<false, kCheckTransaction>(
668 index, static_cast<double>(value));
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100669 break;
Sebastien Hertzee1d79a2014-02-21 15:46:30 +0100670 case Primitive::kPrimNot:
671 LOG(FATAL) << "ObjectArray should be treated as Object";
Elliott Hughesc1896c92018-11-29 11:33:18 -0800672 UNREACHABLE();
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100673 default:
674 LOG(FATAL) << "Unsupported type " << array_type;
Elliott Hughesc1896c92018-11-29 11:33:18 -0800675 UNREACHABLE();
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100676 }
677}
678
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100679} // namespace art