blob: 907d37ef3152ce336fed9ddbfda48a350754c73a [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
19#include "base/stl_util.h"
20#include "base/logging.h"
21#include "gc/accounting/card_table-inl.h"
Andreas Gampe508fdf32017-06-05 16:42:13 -070022#include "gc_root-inl.h"
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +010023#include "intern_table.h"
Mathieu Chartiere401d142015-04-22 13:56:20 -070024#include "mirror/class-inl.h"
Andreas Gampe508fdf32017-06-05 16:42:13 -070025#include "mirror/dex_cache-inl.h"
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +010026#include "mirror/object-inl.h"
27#include "mirror/object_array-inl.h"
28
29#include <list>
30
31namespace art {
32
33// TODO: remove (only used for debugging purpose).
34static constexpr bool kEnableTransactionStats = false;
35
Sebastien Hertz1c80bec2015-02-03 11:58:06 +010036Transaction::Transaction()
37 : log_lock_("transaction log lock", kTransactionLogLock), aborted_(false) {
Mathieu Chartiere5f13e52015-02-24 09:37:21 -080038 CHECK(Runtime::Current()->IsAotCompiler());
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +010039}
40
41Transaction::~Transaction() {
42 if (kEnableTransactionStats) {
43 MutexLock mu(Thread::Current(), log_lock_);
44 size_t objects_count = object_logs_.size();
45 size_t field_values_count = 0;
Mathieu Chartier38e954c2017-02-03 16:06:35 -080046 for (const auto& it : object_logs_) {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +010047 field_values_count += it.second.Size();
48 }
49 size_t array_count = array_logs_.size();
50 size_t array_values_count = 0;
Mathieu Chartier38e954c2017-02-03 16:06:35 -080051 for (const auto& it : array_logs_) {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +010052 array_values_count += it.second.Size();
53 }
Mathieu Chartierbb816d62016-09-07 10:17:46 -070054 size_t intern_string_count = intern_string_logs_.size();
55 size_t resolve_string_count = resolve_string_logs_.size();
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +010056 LOG(INFO) << "Transaction::~Transaction"
57 << ": objects_count=" << objects_count
58 << ", field_values_count=" << field_values_count
59 << ", array_count=" << array_count
60 << ", array_values_count=" << array_values_count
Mathieu Chartierbb816d62016-09-07 10:17:46 -070061 << ", intern_string_count=" << intern_string_count
62 << ", resolve_string_count=" << resolve_string_count;
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +010063 }
64}
65
Sebastien Hertz1c80bec2015-02-03 11:58:06 +010066void Transaction::Abort(const std::string& abort_message) {
67 MutexLock mu(Thread::Current(), log_lock_);
Sebastien Hertz2fd7e692015-04-02 11:11:19 +020068 // We may abort more than once if the exception thrown at the time of the
69 // previous abort has been caught during execution of a class initializer.
Sebastien Hertz1c80bec2015-02-03 11:58:06 +010070 // We just keep the message of the first abort because it will cause the
71 // transaction to be rolled back anyway.
72 if (!aborted_) {
73 aborted_ = true;
74 abort_message_ = abort_message;
75 }
76}
77
Sebastien Hertzb81e1cd2015-04-28 12:31:41 +020078void Transaction::ThrowAbortError(Thread* self, const std::string* abort_message) {
79 const bool rethrow = (abort_message == nullptr);
Sebastien Hertzbd9cf9f2015-03-03 12:16:13 +010080 if (kIsDebugBuild && rethrow) {
Sebastien Hertz2fd7e692015-04-02 11:11:19 +020081 CHECK(IsAborted()) << "Rethrow " << Transaction::kAbortExceptionDescriptor
82 << " while transaction is not aborted";
Sebastien Hertzbd9cf9f2015-03-03 12:16:13 +010083 }
Sebastien Hertzb81e1cd2015-04-28 12:31:41 +020084 if (rethrow) {
85 // Rethrow an exception with the earlier abort message stored in the transaction.
86 self->ThrowNewWrappedException(Transaction::kAbortExceptionSignature,
87 GetAbortMessage().c_str());
88 } else {
89 // Throw an exception with the given abort message.
90 self->ThrowNewWrappedException(Transaction::kAbortExceptionSignature,
91 abort_message->c_str());
92 }
Sebastien Hertz1c80bec2015-02-03 11:58:06 +010093}
94
95bool Transaction::IsAborted() {
96 MutexLock mu(Thread::Current(), log_lock_);
97 return aborted_;
98}
99
100const std::string& Transaction::GetAbortMessage() {
101 MutexLock mu(Thread::Current(), log_lock_);
102 return abort_message_;
103}
104
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800105void Transaction::RecordWriteFieldBoolean(mirror::Object* obj,
106 MemberOffset field_offset,
107 uint8_t value,
108 bool is_volatile) {
Fred Shih37f05ef2014-07-16 18:38:08 -0700109 DCHECK(obj != nullptr);
110 MutexLock mu(Thread::Current(), log_lock_);
111 ObjectLog& object_log = object_logs_[obj];
112 object_log.LogBooleanValue(field_offset, value, is_volatile);
113}
114
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800115void Transaction::RecordWriteFieldByte(mirror::Object* obj,
116 MemberOffset field_offset,
117 int8_t value,
118 bool is_volatile) {
Fred Shih37f05ef2014-07-16 18:38:08 -0700119 DCHECK(obj != nullptr);
120 MutexLock mu(Thread::Current(), log_lock_);
121 ObjectLog& object_log = object_logs_[obj];
122 object_log.LogByteValue(field_offset, value, is_volatile);
123}
124
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800125void Transaction::RecordWriteFieldChar(mirror::Object* obj,
126 MemberOffset field_offset,
127 uint16_t value,
128 bool is_volatile) {
Fred Shih37f05ef2014-07-16 18:38:08 -0700129 DCHECK(obj != nullptr);
130 MutexLock mu(Thread::Current(), log_lock_);
131 ObjectLog& object_log = object_logs_[obj];
132 object_log.LogCharValue(field_offset, value, is_volatile);
133}
134
135
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800136void Transaction::RecordWriteFieldShort(mirror::Object* obj,
137 MemberOffset field_offset,
138 int16_t value,
139 bool is_volatile) {
Fred Shih37f05ef2014-07-16 18:38:08 -0700140 DCHECK(obj != nullptr);
141 MutexLock mu(Thread::Current(), log_lock_);
142 ObjectLog& object_log = object_logs_[obj];
143 object_log.LogShortValue(field_offset, value, is_volatile);
144}
145
146
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800147void Transaction::RecordWriteField32(mirror::Object* obj,
148 MemberOffset field_offset,
149 uint32_t value,
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100150 bool is_volatile) {
151 DCHECK(obj != nullptr);
152 MutexLock mu(Thread::Current(), log_lock_);
153 ObjectLog& object_log = object_logs_[obj];
154 object_log.Log32BitsValue(field_offset, value, is_volatile);
155}
156
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800157void Transaction::RecordWriteField64(mirror::Object* obj,
158 MemberOffset field_offset,
159 uint64_t value,
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100160 bool is_volatile) {
161 DCHECK(obj != nullptr);
162 MutexLock mu(Thread::Current(), log_lock_);
163 ObjectLog& object_log = object_logs_[obj];
164 object_log.Log64BitsValue(field_offset, value, is_volatile);
165}
166
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800167void Transaction::RecordWriteFieldReference(mirror::Object* obj,
168 MemberOffset field_offset,
169 mirror::Object* value,
170 bool is_volatile) {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100171 DCHECK(obj != nullptr);
172 MutexLock mu(Thread::Current(), log_lock_);
173 ObjectLog& object_log = object_logs_[obj];
174 object_log.LogReferenceValue(field_offset, value, is_volatile);
175}
176
177void Transaction::RecordWriteArray(mirror::Array* array, size_t index, uint64_t value) {
178 DCHECK(array != nullptr);
179 DCHECK(array->IsArrayInstance());
Sebastien Hertzee1d79a2014-02-21 15:46:30 +0100180 DCHECK(!array->IsObjectArray());
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100181 MutexLock mu(Thread::Current(), log_lock_);
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800182 auto it = array_logs_.find(array);
183 if (it == array_logs_.end()) {
184 ArrayLog log;
185 it = array_logs_.emplace(array, std::move(log)).first;
186 }
187 it->second.LogValue(index, value);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100188}
189
Andreas Gampe8a0128a2016-11-28 07:38:35 -0800190void Transaction::RecordResolveString(ObjPtr<mirror::DexCache> dex_cache,
191 dex::StringIndex string_idx) {
Mathieu Chartierbb816d62016-09-07 10:17:46 -0700192 DCHECK(dex_cache != nullptr);
Andreas Gampe8a0128a2016-11-28 07:38:35 -0800193 DCHECK_LT(string_idx.index_, dex_cache->GetDexFile()->NumStringIds());
Mathieu Chartierbb816d62016-09-07 10:17:46 -0700194 MutexLock mu(Thread::Current(), log_lock_);
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800195 resolve_string_logs_.emplace_back(dex_cache, string_idx);
Mathieu Chartierbb816d62016-09-07 10:17:46 -0700196}
197
Mathieu Chartier9e868092016-10-31 14:58:04 -0700198void Transaction::RecordStrongStringInsertion(ObjPtr<mirror::String> s) {
Mathieu Chartiercdfd39f2014-08-29 18:16:58 -0700199 InternStringLog log(s, InternStringLog::kStrongString, InternStringLog::kInsert);
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800200 LogInternedString(std::move(log));
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100201}
202
Mathieu Chartier9e868092016-10-31 14:58:04 -0700203void Transaction::RecordWeakStringInsertion(ObjPtr<mirror::String> s) {
Mathieu Chartiercdfd39f2014-08-29 18:16:58 -0700204 InternStringLog log(s, InternStringLog::kWeakString, InternStringLog::kInsert);
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800205 LogInternedString(std::move(log));
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100206}
207
Mathieu Chartier9e868092016-10-31 14:58:04 -0700208void Transaction::RecordStrongStringRemoval(ObjPtr<mirror::String> s) {
Mathieu Chartiercdfd39f2014-08-29 18:16:58 -0700209 InternStringLog log(s, InternStringLog::kStrongString, InternStringLog::kRemove);
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800210 LogInternedString(std::move(log));
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100211}
212
Mathieu Chartier9e868092016-10-31 14:58:04 -0700213void Transaction::RecordWeakStringRemoval(ObjPtr<mirror::String> s) {
Mathieu Chartiercdfd39f2014-08-29 18:16:58 -0700214 InternStringLog log(s, InternStringLog::kWeakString, InternStringLog::kRemove);
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800215 LogInternedString(std::move(log));
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100216}
217
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800218void Transaction::LogInternedString(InternStringLog&& log) {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100219 Locks::intern_table_lock_->AssertExclusiveHeld(Thread::Current());
220 MutexLock mu(Thread::Current(), log_lock_);
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800221 intern_string_logs_.push_front(std::move(log));
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100222}
223
Sebastien Hertz1c80bec2015-02-03 11:58:06 +0100224void Transaction::Rollback() {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100225 CHECK(!Runtime::Current()->IsActiveTransaction());
226 Thread* self = Thread::Current();
227 self->AssertNoPendingException();
228 MutexLock mu1(self, *Locks::intern_table_lock_);
229 MutexLock mu2(self, log_lock_);
230 UndoObjectModifications();
231 UndoArrayModifications();
232 UndoInternStringTableModifications();
Mathieu Chartierbb816d62016-09-07 10:17:46 -0700233 UndoResolveStringModifications();
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100234}
235
236void Transaction::UndoObjectModifications() {
237 // TODO we may not need to restore objects allocated during this transaction. Or we could directly
238 // remove them from the heap.
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800239 for (const auto& it : object_logs_) {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100240 it.second.Undo(it.first);
241 }
242 object_logs_.clear();
243}
244
245void Transaction::UndoArrayModifications() {
246 // TODO we may not need to restore array allocated during this transaction. Or we could directly
247 // remove them from the heap.
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800248 for (const auto& it : array_logs_) {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100249 it.second.Undo(it.first);
250 }
251 array_logs_.clear();
252}
253
254void Transaction::UndoInternStringTableModifications() {
255 InternTable* const intern_table = Runtime::Current()->GetInternTable();
256 // We want to undo each operation from the most recent to the oldest. List has been filled so the
257 // most recent operation is at list begin so just have to iterate over it.
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800258 for (const InternStringLog& string_log : intern_string_logs_) {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100259 string_log.Undo(intern_table);
260 }
261 intern_string_logs_.clear();
262}
263
Mathieu Chartierbb816d62016-09-07 10:17:46 -0700264void Transaction::UndoResolveStringModifications() {
265 for (ResolveStringLog& string_log : resolve_string_logs_) {
266 string_log.Undo();
267 }
268 resolve_string_logs_.clear();
269}
270
Mathieu Chartierbb87e0f2015-04-03 11:21:55 -0700271void Transaction::VisitRoots(RootVisitor* visitor) {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100272 MutexLock mu(Thread::Current(), log_lock_);
Mathieu Chartierbb87e0f2015-04-03 11:21:55 -0700273 VisitObjectLogs(visitor);
274 VisitArrayLogs(visitor);
Mathieu Chartierbb816d62016-09-07 10:17:46 -0700275 VisitInternStringLogs(visitor);
276 VisitResolveStringLogs(visitor);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100277}
278
Mathieu Chartierbb87e0f2015-04-03 11:21:55 -0700279void Transaction::VisitObjectLogs(RootVisitor* visitor) {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100280 // List of moving roots.
281 typedef std::pair<mirror::Object*, mirror::Object*> ObjectPair;
282 std::list<ObjectPair> moving_roots;
283
284 // Visit roots.
Mathieu Chartier5f257b12017-02-03 14:47:36 -0800285 for (auto& it : object_logs_) {
Mathieu Chartierbb87e0f2015-04-03 11:21:55 -0700286 it.second.VisitRoots(visitor);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100287 mirror::Object* old_root = it.first;
Mathieu Chartier815873e2014-02-13 18:02:13 -0800288 mirror::Object* new_root = old_root;
Mathieu Chartierbb87e0f2015-04-03 11:21:55 -0700289 visitor->VisitRoot(&new_root, RootInfo(kRootUnknown));
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100290 if (new_root != old_root) {
291 moving_roots.push_back(std::make_pair(old_root, new_root));
292 }
293 }
294
295 // Update object logs with moving roots.
296 for (const ObjectPair& pair : moving_roots) {
297 mirror::Object* old_root = pair.first;
298 mirror::Object* new_root = pair.second;
299 auto old_root_it = object_logs_.find(old_root);
300 CHECK(old_root_it != object_logs_.end());
301 CHECK(object_logs_.find(new_root) == object_logs_.end());
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800302 object_logs_.emplace(new_root, std::move(old_root_it->second));
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100303 object_logs_.erase(old_root_it);
304 }
305}
306
Mathieu Chartierbb87e0f2015-04-03 11:21:55 -0700307void Transaction::VisitArrayLogs(RootVisitor* visitor) {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100308 // List of moving roots.
309 typedef std::pair<mirror::Array*, mirror::Array*> ArrayPair;
310 std::list<ArrayPair> moving_roots;
311
Mathieu Chartier5f257b12017-02-03 14:47:36 -0800312 for (auto& it : array_logs_) {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100313 mirror::Array* old_root = it.first;
Sebastien Hertzee1d79a2014-02-21 15:46:30 +0100314 CHECK(!old_root->IsObjectArray());
Mathieu Chartier815873e2014-02-13 18:02:13 -0800315 mirror::Array* new_root = old_root;
Mathieu Chartierbb87e0f2015-04-03 11:21:55 -0700316 visitor->VisitRoot(reinterpret_cast<mirror::Object**>(&new_root), RootInfo(kRootUnknown));
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100317 if (new_root != old_root) {
318 moving_roots.push_back(std::make_pair(old_root, new_root));
319 }
320 }
321
322 // Update array logs with moving roots.
323 for (const ArrayPair& pair : moving_roots) {
324 mirror::Array* old_root = pair.first;
325 mirror::Array* new_root = pair.second;
326 auto old_root_it = array_logs_.find(old_root);
327 CHECK(old_root_it != array_logs_.end());
328 CHECK(array_logs_.find(new_root) == array_logs_.end());
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800329 array_logs_.emplace(new_root, std::move(old_root_it->second));
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100330 array_logs_.erase(old_root_it);
331 }
332}
333
Mathieu Chartierbb816d62016-09-07 10:17:46 -0700334void Transaction::VisitInternStringLogs(RootVisitor* visitor) {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100335 for (InternStringLog& log : intern_string_logs_) {
Mathieu Chartierbb87e0f2015-04-03 11:21:55 -0700336 log.VisitRoots(visitor);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100337 }
338}
339
Mathieu Chartierbb816d62016-09-07 10:17:46 -0700340void Transaction::VisitResolveStringLogs(RootVisitor* visitor) {
341 for (ResolveStringLog& log : resolve_string_logs_) {
342 log.VisitRoots(visitor);
343 }
344}
345
Fred Shih37f05ef2014-07-16 18:38:08 -0700346void Transaction::ObjectLog::LogBooleanValue(MemberOffset offset, uint8_t value, bool is_volatile) {
347 LogValue(ObjectLog::kBoolean, offset, value, is_volatile);
348}
349
350void Transaction::ObjectLog::LogByteValue(MemberOffset offset, int8_t value, bool is_volatile) {
351 LogValue(ObjectLog::kByte, offset, value, is_volatile);
352}
353
354void Transaction::ObjectLog::LogCharValue(MemberOffset offset, uint16_t value, bool is_volatile) {
355 LogValue(ObjectLog::kChar, offset, value, is_volatile);
356}
357
358void Transaction::ObjectLog::LogShortValue(MemberOffset offset, int16_t value, bool is_volatile) {
359 LogValue(ObjectLog::kShort, offset, value, is_volatile);
360}
361
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100362void Transaction::ObjectLog::Log32BitsValue(MemberOffset offset, uint32_t value, bool is_volatile) {
Fred Shih37f05ef2014-07-16 18:38:08 -0700363 LogValue(ObjectLog::k32Bits, offset, value, is_volatile);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100364}
365
366void Transaction::ObjectLog::Log64BitsValue(MemberOffset offset, uint64_t value, bool is_volatile) {
Fred Shih37f05ef2014-07-16 18:38:08 -0700367 LogValue(ObjectLog::k64Bits, offset, value, is_volatile);
368}
369
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800370void Transaction::ObjectLog::LogReferenceValue(MemberOffset offset,
371 mirror::Object* obj,
372 bool is_volatile) {
Fred Shih37f05ef2014-07-16 18:38:08 -0700373 LogValue(ObjectLog::kReference, offset, reinterpret_cast<uintptr_t>(obj), is_volatile);
374}
375
376void Transaction::ObjectLog::LogValue(ObjectLog::FieldValueKind kind,
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800377 MemberOffset offset,
378 uint64_t value,
379 bool is_volatile) {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100380 auto it = field_values_.find(offset.Uint32Value());
381 if (it == field_values_.end()) {
382 ObjectLog::FieldValue field_value;
383 field_value.value = value;
384 field_value.is_volatile = is_volatile;
Fred Shih37f05ef2014-07-16 18:38:08 -0700385 field_value.kind = kind;
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800386 field_values_.emplace(offset.Uint32Value(), std::move(field_value));
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100387 }
388}
389
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800390void Transaction::ObjectLog::Undo(mirror::Object* obj) const {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100391 for (auto& it : field_values_) {
392 // Garbage collector needs to access object's class and array's length. So we don't rollback
393 // these values.
394 MemberOffset field_offset(it.first);
395 if (field_offset.Uint32Value() == mirror::Class::ClassOffset().Uint32Value()) {
396 // Skip Object::class field.
397 continue;
398 }
399 if (obj->IsArrayInstance() &&
400 field_offset.Uint32Value() == mirror::Array::LengthOffset().Uint32Value()) {
401 // Skip Array::length field.
402 continue;
403 }
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800404 const FieldValue& field_value = it.second;
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100405 UndoFieldWrite(obj, field_offset, field_value);
406 }
407}
408
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800409void Transaction::ObjectLog::UndoFieldWrite(mirror::Object* obj,
410 MemberOffset field_offset,
411 const FieldValue& field_value) const {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100412 // TODO We may want to abort a transaction while still being in transaction mode. In this case,
413 // we'd need to disable the check.
414 constexpr bool kCheckTransaction = true;
415 switch (field_value.kind) {
Fred Shih37f05ef2014-07-16 18:38:08 -0700416 case kBoolean:
417 if (UNLIKELY(field_value.is_volatile)) {
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800418 obj->SetFieldBooleanVolatile<false, kCheckTransaction>(
419 field_offset,
420 static_cast<bool>(field_value.value));
Fred Shih37f05ef2014-07-16 18:38:08 -0700421 } else {
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800422 obj->SetFieldBoolean<false, kCheckTransaction>(
423 field_offset,
424 static_cast<bool>(field_value.value));
Fred Shih37f05ef2014-07-16 18:38:08 -0700425 }
426 break;
427 case kByte:
428 if (UNLIKELY(field_value.is_volatile)) {
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800429 obj->SetFieldByteVolatile<false, kCheckTransaction>(
430 field_offset,
431 static_cast<int8_t>(field_value.value));
Fred Shih37f05ef2014-07-16 18:38:08 -0700432 } else {
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800433 obj->SetFieldByte<false, kCheckTransaction>(
434 field_offset,
435 static_cast<int8_t>(field_value.value));
Fred Shih37f05ef2014-07-16 18:38:08 -0700436 }
437 break;
438 case kChar:
439 if (UNLIKELY(field_value.is_volatile)) {
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800440 obj->SetFieldCharVolatile<false, kCheckTransaction>(
441 field_offset,
442 static_cast<uint16_t>(field_value.value));
Fred Shih37f05ef2014-07-16 18:38:08 -0700443 } else {
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800444 obj->SetFieldChar<false, kCheckTransaction>(
445 field_offset,
446 static_cast<uint16_t>(field_value.value));
Fred Shih37f05ef2014-07-16 18:38:08 -0700447 }
448 break;
449 case kShort:
450 if (UNLIKELY(field_value.is_volatile)) {
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800451 obj->SetFieldShortVolatile<false, kCheckTransaction>(
452 field_offset,
453 static_cast<int16_t>(field_value.value));
Fred Shih37f05ef2014-07-16 18:38:08 -0700454 } else {
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800455 obj->SetFieldShort<false, kCheckTransaction>(
456 field_offset,
457 static_cast<int16_t>(field_value.value));
Fred Shih37f05ef2014-07-16 18:38:08 -0700458 }
459 break;
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100460 case k32Bits:
Ian Rogersb0fa5dc2014-04-28 16:47:08 -0700461 if (UNLIKELY(field_value.is_volatile)) {
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800462 obj->SetField32Volatile<false, kCheckTransaction>(
463 field_offset,
464 static_cast<uint32_t>(field_value.value));
Ian Rogersb0fa5dc2014-04-28 16:47:08 -0700465 } else {
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800466 obj->SetField32<false, kCheckTransaction>(
467 field_offset,
468 static_cast<uint32_t>(field_value.value));
Ian Rogersb0fa5dc2014-04-28 16:47:08 -0700469 }
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100470 break;
471 case k64Bits:
Ian Rogersb0fa5dc2014-04-28 16:47:08 -0700472 if (UNLIKELY(field_value.is_volatile)) {
473 obj->SetField64Volatile<false, kCheckTransaction>(field_offset, field_value.value);
474 } else {
475 obj->SetField64<false, kCheckTransaction>(field_offset, field_value.value);
476 }
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100477 break;
478 case kReference:
Ian Rogersb0fa5dc2014-04-28 16:47:08 -0700479 if (UNLIKELY(field_value.is_volatile)) {
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800480 obj->SetFieldObjectVolatile<false, kCheckTransaction>(
481 field_offset,
482 reinterpret_cast<mirror::Object*>(field_value.value));
Ian Rogersb0fa5dc2014-04-28 16:47:08 -0700483 } else {
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800484 obj->SetFieldObject<false, kCheckTransaction>(
485 field_offset,
486 reinterpret_cast<mirror::Object*>(field_value.value));
Ian Rogersb0fa5dc2014-04-28 16:47:08 -0700487 }
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100488 break;
489 default:
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700490 LOG(FATAL) << "Unknown value kind " << static_cast<int>(field_value.kind);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100491 break;
492 }
493}
494
Mathieu Chartierbb87e0f2015-04-03 11:21:55 -0700495void Transaction::ObjectLog::VisitRoots(RootVisitor* visitor) {
Mathieu Chartier5f257b12017-02-03 14:47:36 -0800496 for (auto& it : field_values_) {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100497 FieldValue& field_value = it.second;
498 if (field_value.kind == ObjectLog::kReference) {
Mathieu Chartierbb87e0f2015-04-03 11:21:55 -0700499 visitor->VisitRootIfNonNull(reinterpret_cast<mirror::Object**>(&field_value.value),
500 RootInfo(kRootUnknown));
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100501 }
502 }
503}
504
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800505void Transaction::InternStringLog::Undo(InternTable* intern_table) const {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100506 DCHECK(intern_table != nullptr);
507 switch (string_op_) {
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700508 case InternStringLog::kInsert: {
509 switch (string_kind_) {
510 case InternStringLog::kStrongString:
Mathieu Chartier9e868092016-10-31 14:58:04 -0700511 intern_table->RemoveStrongFromTransaction(str_.Read());
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700512 break;
513 case InternStringLog::kWeakString:
Mathieu Chartier9e868092016-10-31 14:58:04 -0700514 intern_table->RemoveWeakFromTransaction(str_.Read());
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700515 break;
516 default:
517 LOG(FATAL) << "Unknown interned string kind";
518 break;
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100519 }
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700520 break;
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100521 }
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700522 case InternStringLog::kRemove: {
523 switch (string_kind_) {
524 case InternStringLog::kStrongString:
Mathieu Chartier9e868092016-10-31 14:58:04 -0700525 intern_table->InsertStrongFromTransaction(str_.Read());
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700526 break;
527 case InternStringLog::kWeakString:
Mathieu Chartier9e868092016-10-31 14:58:04 -0700528 intern_table->InsertWeakFromTransaction(str_.Read());
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700529 break;
530 default:
531 LOG(FATAL) << "Unknown interned string kind";
532 break;
533 }
534 break;
535 }
536 default:
537 LOG(FATAL) << "Unknown interned string op";
538 break;
539 }
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100540}
541
Mathieu Chartierbb87e0f2015-04-03 11:21:55 -0700542void Transaction::InternStringLog::VisitRoots(RootVisitor* visitor) {
Mathieu Chartier9e868092016-10-31 14:58:04 -0700543 str_.VisitRoot(visitor, RootInfo(kRootInternedString));
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100544}
545
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800546void Transaction::ResolveStringLog::Undo() const {
Mathieu Chartierbb816d62016-09-07 10:17:46 -0700547 dex_cache_.Read()->ClearString(string_idx_);
548}
549
Mathieu Chartier9e868092016-10-31 14:58:04 -0700550Transaction::ResolveStringLog::ResolveStringLog(ObjPtr<mirror::DexCache> dex_cache,
Andreas Gampe8a0128a2016-11-28 07:38:35 -0800551 dex::StringIndex string_idx)
Mathieu Chartierbb816d62016-09-07 10:17:46 -0700552 : dex_cache_(dex_cache),
553 string_idx_(string_idx) {
554 DCHECK(dex_cache != nullptr);
Andreas Gampe8a0128a2016-11-28 07:38:35 -0800555 DCHECK_LT(string_idx_.index_, dex_cache->GetDexFile()->NumStringIds());
Mathieu Chartierbb816d62016-09-07 10:17:46 -0700556}
557
558void Transaction::ResolveStringLog::VisitRoots(RootVisitor* visitor) {
559 dex_cache_.VisitRoot(visitor, RootInfo(kRootVMInternal));
560}
561
Mathieu Chartier9e868092016-10-31 14:58:04 -0700562Transaction::InternStringLog::InternStringLog(ObjPtr<mirror::String> s,
563 StringKind kind,
564 StringOp op)
565 : str_(s),
566 string_kind_(kind),
567 string_op_(op) {
568 DCHECK(s != nullptr);
569}
570
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100571void Transaction::ArrayLog::LogValue(size_t index, uint64_t value) {
572 auto it = array_values_.find(index);
573 if (it == array_values_.end()) {
574 array_values_.insert(std::make_pair(index, value));
575 }
576}
577
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800578void Transaction::ArrayLog::Undo(mirror::Array* array) const {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100579 DCHECK(array != nullptr);
580 DCHECK(array->IsArrayInstance());
581 Primitive::Type type = array->GetClass()->GetComponentType()->GetPrimitiveType();
582 for (auto it : array_values_) {
583 UndoArrayWrite(array, type, it.first, it.second);
584 }
585}
586
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800587void Transaction::ArrayLog::UndoArrayWrite(mirror::Array* array,
588 Primitive::Type array_type,
589 size_t index,
590 uint64_t value) const {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100591 // TODO We may want to abort a transaction while still being in transaction mode. In this case,
592 // we'd need to disable the check.
593 switch (array_type) {
594 case Primitive::kPrimBoolean:
595 array->AsBooleanArray()->SetWithoutChecks<false>(index, static_cast<uint8_t>(value));
596 break;
597 case Primitive::kPrimByte:
598 array->AsByteArray()->SetWithoutChecks<false>(index, static_cast<int8_t>(value));
599 break;
600 case Primitive::kPrimChar:
601 array->AsCharArray()->SetWithoutChecks<false>(index, static_cast<uint16_t>(value));
602 break;
603 case Primitive::kPrimShort:
604 array->AsShortArray()->SetWithoutChecks<false>(index, static_cast<int16_t>(value));
605 break;
606 case Primitive::kPrimInt:
607 array->AsIntArray()->SetWithoutChecks<false>(index, static_cast<int32_t>(value));
608 break;
609 case Primitive::kPrimFloat:
610 array->AsFloatArray()->SetWithoutChecks<false>(index, static_cast<float>(value));
611 break;
612 case Primitive::kPrimLong:
613 array->AsLongArray()->SetWithoutChecks<false>(index, static_cast<int64_t>(value));
614 break;
615 case Primitive::kPrimDouble:
616 array->AsDoubleArray()->SetWithoutChecks<false>(index, static_cast<double>(value));
617 break;
Sebastien Hertzee1d79a2014-02-21 15:46:30 +0100618 case Primitive::kPrimNot:
619 LOG(FATAL) << "ObjectArray should be treated as Object";
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100620 break;
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100621 default:
622 LOG(FATAL) << "Unsupported type " << array_type;
623 }
624}
625
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100626} // namespace art