blob: e923aff43905b3cd894eca81fbbf168d9bb4c008 [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
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +010019#include "base/logging.h"
Andreas Gampe8cf9cb32017-07-19 09:28:38 -070020#include "base/stl_util.h"
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +010021#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()
Chang Xing5a906fc2017-07-26 15:01:16 -070037 : log_lock_("transaction log lock", kTransactionLogLock),
38 aborted_(false),
Chang Xing605fe242017-07-20 15:57:21 -070039 rolling_back_(false),
Chang Xing5a906fc2017-07-26 15:01:16 -070040 strict_(false) {
Mathieu Chartiere5f13e52015-02-24 09:37:21 -080041 CHECK(Runtime::Current()->IsAotCompiler());
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +010042}
43
Chang Xing5a906fc2017-07-26 15:01:16 -070044Transaction::Transaction(bool strict, mirror::Class* root) : Transaction() {
45 strict_ = strict;
Chang Xingcade5c32017-07-20 17:56:26 -070046 root_ = root;
47}
48
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +010049Transaction::~Transaction() {
50 if (kEnableTransactionStats) {
51 MutexLock mu(Thread::Current(), log_lock_);
52 size_t objects_count = object_logs_.size();
53 size_t field_values_count = 0;
Mathieu Chartier38e954c2017-02-03 16:06:35 -080054 for (const auto& it : object_logs_) {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +010055 field_values_count += it.second.Size();
56 }
57 size_t array_count = array_logs_.size();
58 size_t array_values_count = 0;
Mathieu Chartier38e954c2017-02-03 16:06:35 -080059 for (const auto& it : array_logs_) {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +010060 array_values_count += it.second.Size();
61 }
Mathieu Chartierbb816d62016-09-07 10:17:46 -070062 size_t intern_string_count = intern_string_logs_.size();
63 size_t resolve_string_count = resolve_string_logs_.size();
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +010064 LOG(INFO) << "Transaction::~Transaction"
65 << ": objects_count=" << objects_count
66 << ", field_values_count=" << field_values_count
67 << ", array_count=" << array_count
68 << ", array_values_count=" << array_values_count
Mathieu Chartierbb816d62016-09-07 10:17:46 -070069 << ", intern_string_count=" << intern_string_count
70 << ", resolve_string_count=" << resolve_string_count;
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +010071 }
72}
73
Sebastien Hertz1c80bec2015-02-03 11:58:06 +010074void Transaction::Abort(const std::string& abort_message) {
75 MutexLock mu(Thread::Current(), log_lock_);
Sebastien Hertz2fd7e692015-04-02 11:11:19 +020076 // We may abort more than once if the exception thrown at the time of the
77 // previous abort has been caught during execution of a class initializer.
Sebastien Hertz1c80bec2015-02-03 11:58:06 +010078 // We just keep the message of the first abort because it will cause the
79 // transaction to be rolled back anyway.
80 if (!aborted_) {
81 aborted_ = true;
82 abort_message_ = abort_message;
83 }
84}
85
Sebastien Hertzb81e1cd2015-04-28 12:31:41 +020086void Transaction::ThrowAbortError(Thread* self, const std::string* abort_message) {
87 const bool rethrow = (abort_message == nullptr);
Sebastien Hertzbd9cf9f2015-03-03 12:16:13 +010088 if (kIsDebugBuild && rethrow) {
Sebastien Hertz2fd7e692015-04-02 11:11:19 +020089 CHECK(IsAborted()) << "Rethrow " << Transaction::kAbortExceptionDescriptor
90 << " while transaction is not aborted";
Sebastien Hertzbd9cf9f2015-03-03 12:16:13 +010091 }
Sebastien Hertzb81e1cd2015-04-28 12:31:41 +020092 if (rethrow) {
93 // Rethrow an exception with the earlier abort message stored in the transaction.
94 self->ThrowNewWrappedException(Transaction::kAbortExceptionSignature,
95 GetAbortMessage().c_str());
96 } else {
97 // Throw an exception with the given abort message.
98 self->ThrowNewWrappedException(Transaction::kAbortExceptionSignature,
99 abort_message->c_str());
100 }
Sebastien Hertz1c80bec2015-02-03 11:58:06 +0100101}
102
103bool Transaction::IsAborted() {
104 MutexLock mu(Thread::Current(), log_lock_);
105 return aborted_;
106}
107
Chang Xing605fe242017-07-20 15:57:21 -0700108bool Transaction::IsRollingBack() {
109 return rolling_back_;
110}
111
Chang Xing5a906fc2017-07-26 15:01:16 -0700112bool Transaction::IsStrict() {
113 MutexLock mu(Thread::Current(), log_lock_);
114 return strict_;
115}
116
Sebastien Hertz1c80bec2015-02-03 11:58:06 +0100117const std::string& Transaction::GetAbortMessage() {
118 MutexLock mu(Thread::Current(), log_lock_);
119 return abort_message_;
120}
121
Chang Xingbd208d82017-07-12 14:53:17 -0700122bool Transaction::WriteConstraint(mirror::Object* obj, ArtField* field) {
123 MutexLock mu(Thread::Current(), log_lock_);
124 if (strict_ // no constraint for boot image
125 && field->IsStatic() // no constraint instance updating
126 && obj != root_) { // modifying other classes' static field, fail
127 return true;
128 }
129 return false;
130}
131
132bool Transaction::ReadConstraint(mirror::Object* obj, ArtField* field) {
133 DCHECK(field->IsStatic());
134 DCHECK(obj->IsClass());
135 MutexLock mu(Thread::Current(), log_lock_);
136 if (!strict_ || // no constraint for boot image
137 obj == root_) { // self-updating, pass
138 return false;
139 }
140 return true;
141}
142
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800143void Transaction::RecordWriteFieldBoolean(mirror::Object* obj,
144 MemberOffset field_offset,
145 uint8_t value,
146 bool is_volatile) {
Fred Shih37f05ef2014-07-16 18:38:08 -0700147 DCHECK(obj != nullptr);
148 MutexLock mu(Thread::Current(), log_lock_);
149 ObjectLog& object_log = object_logs_[obj];
150 object_log.LogBooleanValue(field_offset, value, is_volatile);
151}
152
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800153void Transaction::RecordWriteFieldByte(mirror::Object* obj,
154 MemberOffset field_offset,
155 int8_t value,
156 bool is_volatile) {
Fred Shih37f05ef2014-07-16 18:38:08 -0700157 DCHECK(obj != nullptr);
158 MutexLock mu(Thread::Current(), log_lock_);
159 ObjectLog& object_log = object_logs_[obj];
160 object_log.LogByteValue(field_offset, value, is_volatile);
161}
162
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800163void Transaction::RecordWriteFieldChar(mirror::Object* obj,
164 MemberOffset field_offset,
165 uint16_t value,
166 bool is_volatile) {
Fred Shih37f05ef2014-07-16 18:38:08 -0700167 DCHECK(obj != nullptr);
168 MutexLock mu(Thread::Current(), log_lock_);
169 ObjectLog& object_log = object_logs_[obj];
170 object_log.LogCharValue(field_offset, value, is_volatile);
171}
172
173
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800174void Transaction::RecordWriteFieldShort(mirror::Object* obj,
175 MemberOffset field_offset,
176 int16_t value,
177 bool is_volatile) {
Fred Shih37f05ef2014-07-16 18:38:08 -0700178 DCHECK(obj != nullptr);
179 MutexLock mu(Thread::Current(), log_lock_);
180 ObjectLog& object_log = object_logs_[obj];
181 object_log.LogShortValue(field_offset, value, is_volatile);
182}
183
184
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800185void Transaction::RecordWriteField32(mirror::Object* obj,
186 MemberOffset field_offset,
187 uint32_t value,
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100188 bool is_volatile) {
189 DCHECK(obj != nullptr);
190 MutexLock mu(Thread::Current(), log_lock_);
191 ObjectLog& object_log = object_logs_[obj];
192 object_log.Log32BitsValue(field_offset, value, is_volatile);
193}
194
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800195void Transaction::RecordWriteField64(mirror::Object* obj,
196 MemberOffset field_offset,
197 uint64_t value,
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100198 bool is_volatile) {
199 DCHECK(obj != nullptr);
200 MutexLock mu(Thread::Current(), log_lock_);
201 ObjectLog& object_log = object_logs_[obj];
202 object_log.Log64BitsValue(field_offset, value, is_volatile);
203}
204
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800205void Transaction::RecordWriteFieldReference(mirror::Object* obj,
206 MemberOffset field_offset,
207 mirror::Object* value,
208 bool is_volatile) {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100209 DCHECK(obj != nullptr);
210 MutexLock mu(Thread::Current(), log_lock_);
211 ObjectLog& object_log = object_logs_[obj];
212 object_log.LogReferenceValue(field_offset, value, is_volatile);
213}
214
215void Transaction::RecordWriteArray(mirror::Array* array, size_t index, uint64_t value) {
216 DCHECK(array != nullptr);
217 DCHECK(array->IsArrayInstance());
Sebastien Hertzee1d79a2014-02-21 15:46:30 +0100218 DCHECK(!array->IsObjectArray());
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100219 MutexLock mu(Thread::Current(), log_lock_);
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800220 auto it = array_logs_.find(array);
221 if (it == array_logs_.end()) {
222 ArrayLog log;
223 it = array_logs_.emplace(array, std::move(log)).first;
224 }
225 it->second.LogValue(index, value);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100226}
227
Andreas Gampe8a0128a2016-11-28 07:38:35 -0800228void Transaction::RecordResolveString(ObjPtr<mirror::DexCache> dex_cache,
229 dex::StringIndex string_idx) {
Mathieu Chartierbb816d62016-09-07 10:17:46 -0700230 DCHECK(dex_cache != nullptr);
Andreas Gampe8a0128a2016-11-28 07:38:35 -0800231 DCHECK_LT(string_idx.index_, dex_cache->GetDexFile()->NumStringIds());
Mathieu Chartierbb816d62016-09-07 10:17:46 -0700232 MutexLock mu(Thread::Current(), log_lock_);
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800233 resolve_string_logs_.emplace_back(dex_cache, string_idx);
Mathieu Chartierbb816d62016-09-07 10:17:46 -0700234}
235
Mathieu Chartier9e868092016-10-31 14:58:04 -0700236void Transaction::RecordStrongStringInsertion(ObjPtr<mirror::String> s) {
Mathieu Chartiercdfd39f2014-08-29 18:16:58 -0700237 InternStringLog log(s, InternStringLog::kStrongString, InternStringLog::kInsert);
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800238 LogInternedString(std::move(log));
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100239}
240
Mathieu Chartier9e868092016-10-31 14:58:04 -0700241void Transaction::RecordWeakStringInsertion(ObjPtr<mirror::String> s) {
Mathieu Chartiercdfd39f2014-08-29 18:16:58 -0700242 InternStringLog log(s, InternStringLog::kWeakString, InternStringLog::kInsert);
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800243 LogInternedString(std::move(log));
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100244}
245
Mathieu Chartier9e868092016-10-31 14:58:04 -0700246void Transaction::RecordStrongStringRemoval(ObjPtr<mirror::String> s) {
Mathieu Chartiercdfd39f2014-08-29 18:16:58 -0700247 InternStringLog log(s, InternStringLog::kStrongString, InternStringLog::kRemove);
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800248 LogInternedString(std::move(log));
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100249}
250
Mathieu Chartier9e868092016-10-31 14:58:04 -0700251void Transaction::RecordWeakStringRemoval(ObjPtr<mirror::String> s) {
Mathieu Chartiercdfd39f2014-08-29 18:16:58 -0700252 InternStringLog log(s, InternStringLog::kWeakString, InternStringLog::kRemove);
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800253 LogInternedString(std::move(log));
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100254}
255
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800256void Transaction::LogInternedString(InternStringLog&& log) {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100257 Locks::intern_table_lock_->AssertExclusiveHeld(Thread::Current());
258 MutexLock mu(Thread::Current(), log_lock_);
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800259 intern_string_logs_.push_front(std::move(log));
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100260}
261
Sebastien Hertz1c80bec2015-02-03 11:58:06 +0100262void Transaction::Rollback() {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100263 Thread* self = Thread::Current();
264 self->AssertNoPendingException();
265 MutexLock mu1(self, *Locks::intern_table_lock_);
266 MutexLock mu2(self, log_lock_);
Chang Xing605fe242017-07-20 15:57:21 -0700267 rolling_back_ = true;
268 CHECK(!Runtime::Current()->IsActiveTransaction());
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100269 UndoObjectModifications();
270 UndoArrayModifications();
271 UndoInternStringTableModifications();
Mathieu Chartierbb816d62016-09-07 10:17:46 -0700272 UndoResolveStringModifications();
Chang Xing605fe242017-07-20 15:57:21 -0700273 rolling_back_ = false;
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100274}
275
276void Transaction::UndoObjectModifications() {
277 // TODO we may not need to restore objects allocated during this transaction. Or we could directly
278 // remove them from the heap.
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800279 for (const auto& it : object_logs_) {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100280 it.second.Undo(it.first);
281 }
282 object_logs_.clear();
283}
284
285void Transaction::UndoArrayModifications() {
286 // TODO we may not need to restore array allocated during this transaction. Or we could directly
287 // remove them from the heap.
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800288 for (const auto& it : array_logs_) {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100289 it.second.Undo(it.first);
290 }
291 array_logs_.clear();
292}
293
294void Transaction::UndoInternStringTableModifications() {
295 InternTable* const intern_table = Runtime::Current()->GetInternTable();
296 // We want to undo each operation from the most recent to the oldest. List has been filled so the
297 // most recent operation is at list begin so just have to iterate over it.
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800298 for (const InternStringLog& string_log : intern_string_logs_) {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100299 string_log.Undo(intern_table);
300 }
301 intern_string_logs_.clear();
302}
303
Mathieu Chartierbb816d62016-09-07 10:17:46 -0700304void Transaction::UndoResolveStringModifications() {
305 for (ResolveStringLog& string_log : resolve_string_logs_) {
306 string_log.Undo();
307 }
308 resolve_string_logs_.clear();
309}
310
Mathieu Chartierbb87e0f2015-04-03 11:21:55 -0700311void Transaction::VisitRoots(RootVisitor* visitor) {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100312 MutexLock mu(Thread::Current(), log_lock_);
Chang Xingcade5c32017-07-20 17:56:26 -0700313 visitor->VisitRoot(reinterpret_cast<mirror::Object**>(&root_), RootInfo(kRootUnknown));
Mathieu Chartierbb87e0f2015-04-03 11:21:55 -0700314 VisitObjectLogs(visitor);
315 VisitArrayLogs(visitor);
Mathieu Chartierbb816d62016-09-07 10:17:46 -0700316 VisitInternStringLogs(visitor);
317 VisitResolveStringLogs(visitor);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100318}
319
Mathieu Chartierbb87e0f2015-04-03 11:21:55 -0700320void Transaction::VisitObjectLogs(RootVisitor* visitor) {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100321 // List of moving roots.
322 typedef std::pair<mirror::Object*, mirror::Object*> ObjectPair;
323 std::list<ObjectPair> moving_roots;
324
325 // Visit roots.
Mathieu Chartier5f257b12017-02-03 14:47:36 -0800326 for (auto& it : object_logs_) {
Mathieu Chartierbb87e0f2015-04-03 11:21:55 -0700327 it.second.VisitRoots(visitor);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100328 mirror::Object* old_root = it.first;
Mathieu Chartier815873e2014-02-13 18:02:13 -0800329 mirror::Object* new_root = old_root;
Mathieu Chartierbb87e0f2015-04-03 11:21:55 -0700330 visitor->VisitRoot(&new_root, RootInfo(kRootUnknown));
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100331 if (new_root != old_root) {
332 moving_roots.push_back(std::make_pair(old_root, new_root));
333 }
334 }
335
336 // Update object logs with moving roots.
337 for (const ObjectPair& pair : moving_roots) {
338 mirror::Object* old_root = pair.first;
339 mirror::Object* new_root = pair.second;
340 auto old_root_it = object_logs_.find(old_root);
341 CHECK(old_root_it != object_logs_.end());
342 CHECK(object_logs_.find(new_root) == object_logs_.end());
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800343 object_logs_.emplace(new_root, std::move(old_root_it->second));
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100344 object_logs_.erase(old_root_it);
345 }
346}
347
Mathieu Chartierbb87e0f2015-04-03 11:21:55 -0700348void Transaction::VisitArrayLogs(RootVisitor* visitor) {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100349 // List of moving roots.
350 typedef std::pair<mirror::Array*, mirror::Array*> ArrayPair;
351 std::list<ArrayPair> moving_roots;
352
Mathieu Chartier5f257b12017-02-03 14:47:36 -0800353 for (auto& it : array_logs_) {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100354 mirror::Array* old_root = it.first;
Sebastien Hertzee1d79a2014-02-21 15:46:30 +0100355 CHECK(!old_root->IsObjectArray());
Mathieu Chartier815873e2014-02-13 18:02:13 -0800356 mirror::Array* new_root = old_root;
Mathieu Chartierbb87e0f2015-04-03 11:21:55 -0700357 visitor->VisitRoot(reinterpret_cast<mirror::Object**>(&new_root), RootInfo(kRootUnknown));
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100358 if (new_root != old_root) {
359 moving_roots.push_back(std::make_pair(old_root, new_root));
360 }
361 }
362
363 // Update array logs with moving roots.
364 for (const ArrayPair& pair : moving_roots) {
365 mirror::Array* old_root = pair.first;
366 mirror::Array* new_root = pair.second;
367 auto old_root_it = array_logs_.find(old_root);
368 CHECK(old_root_it != array_logs_.end());
369 CHECK(array_logs_.find(new_root) == array_logs_.end());
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800370 array_logs_.emplace(new_root, std::move(old_root_it->second));
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100371 array_logs_.erase(old_root_it);
372 }
373}
374
Mathieu Chartierbb816d62016-09-07 10:17:46 -0700375void Transaction::VisitInternStringLogs(RootVisitor* visitor) {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100376 for (InternStringLog& log : intern_string_logs_) {
Mathieu Chartierbb87e0f2015-04-03 11:21:55 -0700377 log.VisitRoots(visitor);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100378 }
379}
380
Mathieu Chartierbb816d62016-09-07 10:17:46 -0700381void Transaction::VisitResolveStringLogs(RootVisitor* visitor) {
382 for (ResolveStringLog& log : resolve_string_logs_) {
383 log.VisitRoots(visitor);
384 }
385}
386
Fred Shih37f05ef2014-07-16 18:38:08 -0700387void Transaction::ObjectLog::LogBooleanValue(MemberOffset offset, uint8_t value, bool is_volatile) {
388 LogValue(ObjectLog::kBoolean, offset, value, is_volatile);
389}
390
391void Transaction::ObjectLog::LogByteValue(MemberOffset offset, int8_t value, bool is_volatile) {
392 LogValue(ObjectLog::kByte, offset, value, is_volatile);
393}
394
395void Transaction::ObjectLog::LogCharValue(MemberOffset offset, uint16_t value, bool is_volatile) {
396 LogValue(ObjectLog::kChar, offset, value, is_volatile);
397}
398
399void Transaction::ObjectLog::LogShortValue(MemberOffset offset, int16_t value, bool is_volatile) {
400 LogValue(ObjectLog::kShort, offset, value, is_volatile);
401}
402
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100403void Transaction::ObjectLog::Log32BitsValue(MemberOffset offset, uint32_t value, bool is_volatile) {
Fred Shih37f05ef2014-07-16 18:38:08 -0700404 LogValue(ObjectLog::k32Bits, offset, value, is_volatile);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100405}
406
407void Transaction::ObjectLog::Log64BitsValue(MemberOffset offset, uint64_t value, bool is_volatile) {
Fred Shih37f05ef2014-07-16 18:38:08 -0700408 LogValue(ObjectLog::k64Bits, offset, value, is_volatile);
409}
410
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800411void Transaction::ObjectLog::LogReferenceValue(MemberOffset offset,
412 mirror::Object* obj,
413 bool is_volatile) {
Fred Shih37f05ef2014-07-16 18:38:08 -0700414 LogValue(ObjectLog::kReference, offset, reinterpret_cast<uintptr_t>(obj), is_volatile);
415}
416
417void Transaction::ObjectLog::LogValue(ObjectLog::FieldValueKind kind,
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800418 MemberOffset offset,
419 uint64_t value,
420 bool is_volatile) {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100421 auto it = field_values_.find(offset.Uint32Value());
422 if (it == field_values_.end()) {
423 ObjectLog::FieldValue field_value;
424 field_value.value = value;
425 field_value.is_volatile = is_volatile;
Fred Shih37f05ef2014-07-16 18:38:08 -0700426 field_value.kind = kind;
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800427 field_values_.emplace(offset.Uint32Value(), std::move(field_value));
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100428 }
429}
430
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800431void Transaction::ObjectLog::Undo(mirror::Object* obj) const {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100432 for (auto& it : field_values_) {
433 // Garbage collector needs to access object's class and array's length. So we don't rollback
434 // these values.
435 MemberOffset field_offset(it.first);
436 if (field_offset.Uint32Value() == mirror::Class::ClassOffset().Uint32Value()) {
437 // Skip Object::class field.
438 continue;
439 }
440 if (obj->IsArrayInstance() &&
441 field_offset.Uint32Value() == mirror::Array::LengthOffset().Uint32Value()) {
442 // Skip Array::length field.
443 continue;
444 }
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800445 const FieldValue& field_value = it.second;
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100446 UndoFieldWrite(obj, field_offset, field_value);
447 }
448}
449
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800450void Transaction::ObjectLog::UndoFieldWrite(mirror::Object* obj,
451 MemberOffset field_offset,
452 const FieldValue& field_value) const {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100453 // TODO We may want to abort a transaction while still being in transaction mode. In this case,
454 // we'd need to disable the check.
Chang Xing605fe242017-07-20 15:57:21 -0700455 constexpr bool kCheckTransaction = false;
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100456 switch (field_value.kind) {
Fred Shih37f05ef2014-07-16 18:38:08 -0700457 case kBoolean:
458 if (UNLIKELY(field_value.is_volatile)) {
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800459 obj->SetFieldBooleanVolatile<false, kCheckTransaction>(
460 field_offset,
461 static_cast<bool>(field_value.value));
Fred Shih37f05ef2014-07-16 18:38:08 -0700462 } else {
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800463 obj->SetFieldBoolean<false, kCheckTransaction>(
464 field_offset,
465 static_cast<bool>(field_value.value));
Fred Shih37f05ef2014-07-16 18:38:08 -0700466 }
467 break;
468 case kByte:
469 if (UNLIKELY(field_value.is_volatile)) {
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800470 obj->SetFieldByteVolatile<false, kCheckTransaction>(
471 field_offset,
472 static_cast<int8_t>(field_value.value));
Fred Shih37f05ef2014-07-16 18:38:08 -0700473 } else {
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800474 obj->SetFieldByte<false, kCheckTransaction>(
475 field_offset,
476 static_cast<int8_t>(field_value.value));
Fred Shih37f05ef2014-07-16 18:38:08 -0700477 }
478 break;
479 case kChar:
480 if (UNLIKELY(field_value.is_volatile)) {
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800481 obj->SetFieldCharVolatile<false, kCheckTransaction>(
482 field_offset,
483 static_cast<uint16_t>(field_value.value));
Fred Shih37f05ef2014-07-16 18:38:08 -0700484 } else {
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800485 obj->SetFieldChar<false, kCheckTransaction>(
486 field_offset,
487 static_cast<uint16_t>(field_value.value));
Fred Shih37f05ef2014-07-16 18:38:08 -0700488 }
489 break;
490 case kShort:
491 if (UNLIKELY(field_value.is_volatile)) {
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800492 obj->SetFieldShortVolatile<false, kCheckTransaction>(
493 field_offset,
494 static_cast<int16_t>(field_value.value));
Fred Shih37f05ef2014-07-16 18:38:08 -0700495 } else {
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800496 obj->SetFieldShort<false, kCheckTransaction>(
497 field_offset,
498 static_cast<int16_t>(field_value.value));
Fred Shih37f05ef2014-07-16 18:38:08 -0700499 }
500 break;
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100501 case k32Bits:
Ian Rogersb0fa5dc2014-04-28 16:47:08 -0700502 if (UNLIKELY(field_value.is_volatile)) {
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800503 obj->SetField32Volatile<false, kCheckTransaction>(
504 field_offset,
505 static_cast<uint32_t>(field_value.value));
Ian Rogersb0fa5dc2014-04-28 16:47:08 -0700506 } else {
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800507 obj->SetField32<false, kCheckTransaction>(
508 field_offset,
509 static_cast<uint32_t>(field_value.value));
Ian Rogersb0fa5dc2014-04-28 16:47:08 -0700510 }
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100511 break;
512 case k64Bits:
Ian Rogersb0fa5dc2014-04-28 16:47:08 -0700513 if (UNLIKELY(field_value.is_volatile)) {
514 obj->SetField64Volatile<false, kCheckTransaction>(field_offset, field_value.value);
515 } else {
516 obj->SetField64<false, kCheckTransaction>(field_offset, field_value.value);
517 }
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100518 break;
519 case kReference:
Ian Rogersb0fa5dc2014-04-28 16:47:08 -0700520 if (UNLIKELY(field_value.is_volatile)) {
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800521 obj->SetFieldObjectVolatile<false, kCheckTransaction>(
522 field_offset,
523 reinterpret_cast<mirror::Object*>(field_value.value));
Ian Rogersb0fa5dc2014-04-28 16:47:08 -0700524 } else {
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800525 obj->SetFieldObject<false, kCheckTransaction>(
526 field_offset,
527 reinterpret_cast<mirror::Object*>(field_value.value));
Ian Rogersb0fa5dc2014-04-28 16:47:08 -0700528 }
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100529 break;
530 default:
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700531 LOG(FATAL) << "Unknown value kind " << static_cast<int>(field_value.kind);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100532 break;
533 }
534}
535
Mathieu Chartierbb87e0f2015-04-03 11:21:55 -0700536void Transaction::ObjectLog::VisitRoots(RootVisitor* visitor) {
Mathieu Chartier5f257b12017-02-03 14:47:36 -0800537 for (auto& it : field_values_) {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100538 FieldValue& field_value = it.second;
539 if (field_value.kind == ObjectLog::kReference) {
Mathieu Chartierbb87e0f2015-04-03 11:21:55 -0700540 visitor->VisitRootIfNonNull(reinterpret_cast<mirror::Object**>(&field_value.value),
541 RootInfo(kRootUnknown));
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100542 }
543 }
544}
545
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800546void Transaction::InternStringLog::Undo(InternTable* intern_table) const {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100547 DCHECK(intern_table != nullptr);
548 switch (string_op_) {
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700549 case InternStringLog::kInsert: {
550 switch (string_kind_) {
551 case InternStringLog::kStrongString:
Mathieu Chartier9e868092016-10-31 14:58:04 -0700552 intern_table->RemoveStrongFromTransaction(str_.Read());
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700553 break;
554 case InternStringLog::kWeakString:
Mathieu Chartier9e868092016-10-31 14:58:04 -0700555 intern_table->RemoveWeakFromTransaction(str_.Read());
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700556 break;
557 default:
558 LOG(FATAL) << "Unknown interned string kind";
559 break;
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100560 }
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700561 break;
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100562 }
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700563 case InternStringLog::kRemove: {
564 switch (string_kind_) {
565 case InternStringLog::kStrongString:
Mathieu Chartier9e868092016-10-31 14:58:04 -0700566 intern_table->InsertStrongFromTransaction(str_.Read());
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700567 break;
568 case InternStringLog::kWeakString:
Mathieu Chartier9e868092016-10-31 14:58:04 -0700569 intern_table->InsertWeakFromTransaction(str_.Read());
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700570 break;
571 default:
572 LOG(FATAL) << "Unknown interned string kind";
573 break;
574 }
575 break;
576 }
577 default:
578 LOG(FATAL) << "Unknown interned string op";
579 break;
580 }
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100581}
582
Mathieu Chartierbb87e0f2015-04-03 11:21:55 -0700583void Transaction::InternStringLog::VisitRoots(RootVisitor* visitor) {
Mathieu Chartier9e868092016-10-31 14:58:04 -0700584 str_.VisitRoot(visitor, RootInfo(kRootInternedString));
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100585}
586
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800587void Transaction::ResolveStringLog::Undo() const {
Mathieu Chartierbb816d62016-09-07 10:17:46 -0700588 dex_cache_.Read()->ClearString(string_idx_);
589}
590
Mathieu Chartier9e868092016-10-31 14:58:04 -0700591Transaction::ResolveStringLog::ResolveStringLog(ObjPtr<mirror::DexCache> dex_cache,
Andreas Gampe8a0128a2016-11-28 07:38:35 -0800592 dex::StringIndex string_idx)
Mathieu Chartierbb816d62016-09-07 10:17:46 -0700593 : dex_cache_(dex_cache),
594 string_idx_(string_idx) {
595 DCHECK(dex_cache != nullptr);
Andreas Gampe8a0128a2016-11-28 07:38:35 -0800596 DCHECK_LT(string_idx_.index_, dex_cache->GetDexFile()->NumStringIds());
Mathieu Chartierbb816d62016-09-07 10:17:46 -0700597}
598
599void Transaction::ResolveStringLog::VisitRoots(RootVisitor* visitor) {
600 dex_cache_.VisitRoot(visitor, RootInfo(kRootVMInternal));
601}
602
Mathieu Chartier9e868092016-10-31 14:58:04 -0700603Transaction::InternStringLog::InternStringLog(ObjPtr<mirror::String> s,
604 StringKind kind,
605 StringOp op)
606 : str_(s),
607 string_kind_(kind),
608 string_op_(op) {
609 DCHECK(s != nullptr);
610}
611
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100612void Transaction::ArrayLog::LogValue(size_t index, uint64_t value) {
613 auto it = array_values_.find(index);
614 if (it == array_values_.end()) {
615 array_values_.insert(std::make_pair(index, value));
616 }
617}
618
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800619void Transaction::ArrayLog::Undo(mirror::Array* array) const {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100620 DCHECK(array != nullptr);
621 DCHECK(array->IsArrayInstance());
622 Primitive::Type type = array->GetClass()->GetComponentType()->GetPrimitiveType();
623 for (auto it : array_values_) {
624 UndoArrayWrite(array, type, it.first, it.second);
625 }
626}
627
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800628void Transaction::ArrayLog::UndoArrayWrite(mirror::Array* array,
629 Primitive::Type array_type,
630 size_t index,
631 uint64_t value) const {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100632 // TODO We may want to abort a transaction while still being in transaction mode. In this case,
633 // we'd need to disable the check.
Chang Xing605fe242017-07-20 15:57:21 -0700634 constexpr bool kCheckTransaction = false;
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100635 switch (array_type) {
636 case Primitive::kPrimBoolean:
Chang Xing605fe242017-07-20 15:57:21 -0700637 array->AsBooleanArray()->SetWithoutChecks<false, kCheckTransaction>(
638 index, static_cast<uint8_t>(value));
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100639 break;
640 case Primitive::kPrimByte:
Chang Xing605fe242017-07-20 15:57:21 -0700641 array->AsByteArray()->SetWithoutChecks<false, kCheckTransaction>(
642 index, static_cast<int8_t>(value));
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100643 break;
644 case Primitive::kPrimChar:
Chang Xing605fe242017-07-20 15:57:21 -0700645 array->AsCharArray()->SetWithoutChecks<false, kCheckTransaction>(
646 index, static_cast<uint16_t>(value));
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100647 break;
648 case Primitive::kPrimShort:
Chang Xing605fe242017-07-20 15:57:21 -0700649 array->AsShortArray()->SetWithoutChecks<false, kCheckTransaction>(
650 index, static_cast<int16_t>(value));
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100651 break;
652 case Primitive::kPrimInt:
Chang Xing605fe242017-07-20 15:57:21 -0700653 array->AsIntArray()->SetWithoutChecks<false, kCheckTransaction>(
654 index, static_cast<int32_t>(value));
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100655 break;
656 case Primitive::kPrimFloat:
Chang Xing605fe242017-07-20 15:57:21 -0700657 array->AsFloatArray()->SetWithoutChecks<false, kCheckTransaction>(
658 index, static_cast<float>(value));
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100659 break;
660 case Primitive::kPrimLong:
Chang Xing605fe242017-07-20 15:57:21 -0700661 array->AsLongArray()->SetWithoutChecks<false, kCheckTransaction>(
662 index, static_cast<int64_t>(value));
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100663 break;
664 case Primitive::kPrimDouble:
Chang Xing605fe242017-07-20 15:57:21 -0700665 array->AsDoubleArray()->SetWithoutChecks<false, kCheckTransaction>(
666 index, static_cast<double>(value));
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100667 break;
Sebastien Hertzee1d79a2014-02-21 15:46:30 +0100668 case Primitive::kPrimNot:
669 LOG(FATAL) << "ObjectArray should be treated as Object";
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100670 break;
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100671 default:
672 LOG(FATAL) << "Unsupported type " << array_type;
673 }
674}
675
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100676} // namespace art