blob: c9766bc9ca3774d33ca759e87669a1e8b0024f72 [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 Gampe8cf9cb32017-07-19 09:28:38 -070021#include "base/stl_util.h"
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +010022#include "gc/accounting/card_table-inl.h"
Andreas Gampe508fdf32017-06-05 16:42:13 -070023#include "gc_root-inl.h"
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +010024#include "intern_table.h"
Mathieu Chartiere401d142015-04-22 13:56:20 -070025#include "mirror/class-inl.h"
Andreas Gampe508fdf32017-06-05 16:42:13 -070026#include "mirror/dex_cache-inl.h"
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +010027#include "mirror/object-inl.h"
28#include "mirror/object_array-inl.h"
29
30#include <list>
31
32namespace art {
33
34// TODO: remove (only used for debugging purpose).
35static constexpr bool kEnableTransactionStats = false;
36
Sebastien Hertz1c80bec2015-02-03 11:58:06 +010037Transaction::Transaction()
Chang Xing5a906fc2017-07-26 15:01:16 -070038 : log_lock_("transaction log lock", kTransactionLogLock),
39 aborted_(false),
Chang Xing605fe242017-07-20 15:57:21 -070040 rolling_back_(false),
Chang Xing5a906fc2017-07-26 15:01:16 -070041 strict_(false) {
Mathieu Chartiere5f13e52015-02-24 09:37:21 -080042 CHECK(Runtime::Current()->IsAotCompiler());
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +010043}
44
Chang Xing5a906fc2017-07-26 15:01:16 -070045Transaction::Transaction(bool strict, mirror::Class* root) : Transaction() {
46 strict_ = strict;
Chang Xingcade5c32017-07-20 17:56:26 -070047 root_ = root;
48}
49
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +010050Transaction::~Transaction() {
51 if (kEnableTransactionStats) {
52 MutexLock mu(Thread::Current(), log_lock_);
53 size_t objects_count = object_logs_.size();
54 size_t field_values_count = 0;
Mathieu Chartier38e954c2017-02-03 16:06:35 -080055 for (const auto& it : object_logs_) {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +010056 field_values_count += it.second.Size();
57 }
58 size_t array_count = array_logs_.size();
59 size_t array_values_count = 0;
Mathieu Chartier38e954c2017-02-03 16:06:35 -080060 for (const auto& it : array_logs_) {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +010061 array_values_count += it.second.Size();
62 }
Mathieu Chartierbb816d62016-09-07 10:17:46 -070063 size_t intern_string_count = intern_string_logs_.size();
64 size_t resolve_string_count = resolve_string_logs_.size();
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +010065 LOG(INFO) << "Transaction::~Transaction"
66 << ": objects_count=" << objects_count
67 << ", field_values_count=" << field_values_count
68 << ", array_count=" << array_count
69 << ", array_values_count=" << array_values_count
Mathieu Chartierbb816d62016-09-07 10:17:46 -070070 << ", intern_string_count=" << intern_string_count
71 << ", resolve_string_count=" << resolve_string_count;
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +010072 }
73}
74
Sebastien Hertz1c80bec2015-02-03 11:58:06 +010075void Transaction::Abort(const std::string& abort_message) {
76 MutexLock mu(Thread::Current(), log_lock_);
Sebastien Hertz2fd7e692015-04-02 11:11:19 +020077 // We may abort more than once if the exception thrown at the time of the
78 // previous abort has been caught during execution of a class initializer.
Sebastien Hertz1c80bec2015-02-03 11:58:06 +010079 // We just keep the message of the first abort because it will cause the
80 // transaction to be rolled back anyway.
81 if (!aborted_) {
82 aborted_ = true;
83 abort_message_ = abort_message;
84 }
85}
86
Sebastien Hertzb81e1cd2015-04-28 12:31:41 +020087void Transaction::ThrowAbortError(Thread* self, const std::string* abort_message) {
88 const bool rethrow = (abort_message == nullptr);
Sebastien Hertzbd9cf9f2015-03-03 12:16:13 +010089 if (kIsDebugBuild && rethrow) {
Sebastien Hertz2fd7e692015-04-02 11:11:19 +020090 CHECK(IsAborted()) << "Rethrow " << Transaction::kAbortExceptionDescriptor
91 << " while transaction is not aborted";
Sebastien Hertzbd9cf9f2015-03-03 12:16:13 +010092 }
Sebastien Hertzb81e1cd2015-04-28 12:31:41 +020093 if (rethrow) {
94 // Rethrow an exception with the earlier abort message stored in the transaction.
95 self->ThrowNewWrappedException(Transaction::kAbortExceptionSignature,
96 GetAbortMessage().c_str());
97 } else {
98 // Throw an exception with the given abort message.
99 self->ThrowNewWrappedException(Transaction::kAbortExceptionSignature,
100 abort_message->c_str());
101 }
Sebastien Hertz1c80bec2015-02-03 11:58:06 +0100102}
103
104bool Transaction::IsAborted() {
105 MutexLock mu(Thread::Current(), log_lock_);
106 return aborted_;
107}
108
Chang Xing605fe242017-07-20 15:57:21 -0700109bool Transaction::IsRollingBack() {
110 return rolling_back_;
111}
112
Chang Xing5a906fc2017-07-26 15:01:16 -0700113bool Transaction::IsStrict() {
114 MutexLock mu(Thread::Current(), log_lock_);
115 return strict_;
116}
117
Sebastien Hertz1c80bec2015-02-03 11:58:06 +0100118const std::string& Transaction::GetAbortMessage() {
119 MutexLock mu(Thread::Current(), log_lock_);
120 return abort_message_;
121}
122
Chang Xingbd208d82017-07-12 14:53:17 -0700123bool Transaction::WriteConstraint(mirror::Object* obj, ArtField* field) {
124 MutexLock mu(Thread::Current(), log_lock_);
125 if (strict_ // no constraint for boot image
126 && field->IsStatic() // no constraint instance updating
127 && obj != root_) { // modifying other classes' static field, fail
128 return true;
129 }
130 return false;
131}
132
133bool Transaction::ReadConstraint(mirror::Object* obj, ArtField* field) {
134 DCHECK(field->IsStatic());
135 DCHECK(obj->IsClass());
136 MutexLock mu(Thread::Current(), log_lock_);
137 if (!strict_ || // no constraint for boot image
138 obj == root_) { // self-updating, pass
139 return false;
140 }
141 return true;
142}
143
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800144void Transaction::RecordWriteFieldBoolean(mirror::Object* obj,
145 MemberOffset field_offset,
146 uint8_t value,
147 bool is_volatile) {
Fred Shih37f05ef2014-07-16 18:38:08 -0700148 DCHECK(obj != nullptr);
149 MutexLock mu(Thread::Current(), log_lock_);
150 ObjectLog& object_log = object_logs_[obj];
151 object_log.LogBooleanValue(field_offset, value, is_volatile);
152}
153
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800154void Transaction::RecordWriteFieldByte(mirror::Object* obj,
155 MemberOffset field_offset,
156 int8_t value,
157 bool is_volatile) {
Fred Shih37f05ef2014-07-16 18:38:08 -0700158 DCHECK(obj != nullptr);
159 MutexLock mu(Thread::Current(), log_lock_);
160 ObjectLog& object_log = object_logs_[obj];
161 object_log.LogByteValue(field_offset, value, is_volatile);
162}
163
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800164void Transaction::RecordWriteFieldChar(mirror::Object* obj,
165 MemberOffset field_offset,
166 uint16_t value,
167 bool is_volatile) {
Fred Shih37f05ef2014-07-16 18:38:08 -0700168 DCHECK(obj != nullptr);
169 MutexLock mu(Thread::Current(), log_lock_);
170 ObjectLog& object_log = object_logs_[obj];
171 object_log.LogCharValue(field_offset, value, is_volatile);
172}
173
174
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800175void Transaction::RecordWriteFieldShort(mirror::Object* obj,
176 MemberOffset field_offset,
177 int16_t value,
178 bool is_volatile) {
Fred Shih37f05ef2014-07-16 18:38:08 -0700179 DCHECK(obj != nullptr);
180 MutexLock mu(Thread::Current(), log_lock_);
181 ObjectLog& object_log = object_logs_[obj];
182 object_log.LogShortValue(field_offset, value, is_volatile);
183}
184
185
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800186void Transaction::RecordWriteField32(mirror::Object* obj,
187 MemberOffset field_offset,
188 uint32_t value,
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100189 bool is_volatile) {
190 DCHECK(obj != nullptr);
191 MutexLock mu(Thread::Current(), log_lock_);
192 ObjectLog& object_log = object_logs_[obj];
193 object_log.Log32BitsValue(field_offset, value, is_volatile);
194}
195
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800196void Transaction::RecordWriteField64(mirror::Object* obj,
197 MemberOffset field_offset,
198 uint64_t value,
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100199 bool is_volatile) {
200 DCHECK(obj != nullptr);
201 MutexLock mu(Thread::Current(), log_lock_);
202 ObjectLog& object_log = object_logs_[obj];
203 object_log.Log64BitsValue(field_offset, value, is_volatile);
204}
205
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800206void Transaction::RecordWriteFieldReference(mirror::Object* obj,
207 MemberOffset field_offset,
208 mirror::Object* value,
209 bool is_volatile) {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100210 DCHECK(obj != nullptr);
211 MutexLock mu(Thread::Current(), log_lock_);
212 ObjectLog& object_log = object_logs_[obj];
213 object_log.LogReferenceValue(field_offset, value, is_volatile);
214}
215
216void Transaction::RecordWriteArray(mirror::Array* array, size_t index, uint64_t value) {
217 DCHECK(array != nullptr);
218 DCHECK(array->IsArrayInstance());
Sebastien Hertzee1d79a2014-02-21 15:46:30 +0100219 DCHECK(!array->IsObjectArray());
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100220 MutexLock mu(Thread::Current(), log_lock_);
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800221 auto it = array_logs_.find(array);
222 if (it == array_logs_.end()) {
223 ArrayLog log;
224 it = array_logs_.emplace(array, std::move(log)).first;
225 }
226 it->second.LogValue(index, value);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100227}
228
Andreas Gampe8a0128a2016-11-28 07:38:35 -0800229void Transaction::RecordResolveString(ObjPtr<mirror::DexCache> dex_cache,
230 dex::StringIndex string_idx) {
Mathieu Chartierbb816d62016-09-07 10:17:46 -0700231 DCHECK(dex_cache != nullptr);
Andreas Gampe8a0128a2016-11-28 07:38:35 -0800232 DCHECK_LT(string_idx.index_, dex_cache->GetDexFile()->NumStringIds());
Mathieu Chartierbb816d62016-09-07 10:17:46 -0700233 MutexLock mu(Thread::Current(), log_lock_);
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800234 resolve_string_logs_.emplace_back(dex_cache, string_idx);
Mathieu Chartierbb816d62016-09-07 10:17:46 -0700235}
236
Mathieu Chartier9e868092016-10-31 14:58:04 -0700237void Transaction::RecordStrongStringInsertion(ObjPtr<mirror::String> s) {
Mathieu Chartiercdfd39f2014-08-29 18:16:58 -0700238 InternStringLog log(s, InternStringLog::kStrongString, InternStringLog::kInsert);
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800239 LogInternedString(std::move(log));
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100240}
241
Mathieu Chartier9e868092016-10-31 14:58:04 -0700242void Transaction::RecordWeakStringInsertion(ObjPtr<mirror::String> s) {
Mathieu Chartiercdfd39f2014-08-29 18:16:58 -0700243 InternStringLog log(s, InternStringLog::kWeakString, InternStringLog::kInsert);
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800244 LogInternedString(std::move(log));
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100245}
246
Mathieu Chartier9e868092016-10-31 14:58:04 -0700247void Transaction::RecordStrongStringRemoval(ObjPtr<mirror::String> s) {
Mathieu Chartiercdfd39f2014-08-29 18:16:58 -0700248 InternStringLog log(s, InternStringLog::kStrongString, InternStringLog::kRemove);
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800249 LogInternedString(std::move(log));
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100250}
251
Mathieu Chartier9e868092016-10-31 14:58:04 -0700252void Transaction::RecordWeakStringRemoval(ObjPtr<mirror::String> s) {
Mathieu Chartiercdfd39f2014-08-29 18:16:58 -0700253 InternStringLog log(s, InternStringLog::kWeakString, InternStringLog::kRemove);
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800254 LogInternedString(std::move(log));
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100255}
256
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800257void Transaction::LogInternedString(InternStringLog&& log) {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100258 Locks::intern_table_lock_->AssertExclusiveHeld(Thread::Current());
259 MutexLock mu(Thread::Current(), log_lock_);
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800260 intern_string_logs_.push_front(std::move(log));
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100261}
262
Sebastien Hertz1c80bec2015-02-03 11:58:06 +0100263void Transaction::Rollback() {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100264 Thread* self = Thread::Current();
265 self->AssertNoPendingException();
266 MutexLock mu1(self, *Locks::intern_table_lock_);
267 MutexLock mu2(self, log_lock_);
Chang Xing605fe242017-07-20 15:57:21 -0700268 rolling_back_ = true;
269 CHECK(!Runtime::Current()->IsActiveTransaction());
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100270 UndoObjectModifications();
271 UndoArrayModifications();
272 UndoInternStringTableModifications();
Mathieu Chartierbb816d62016-09-07 10:17:46 -0700273 UndoResolveStringModifications();
Chang Xing605fe242017-07-20 15:57:21 -0700274 rolling_back_ = false;
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100275}
276
277void Transaction::UndoObjectModifications() {
278 // TODO we may not need to restore objects allocated during this transaction. Or we could directly
279 // remove them from the heap.
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800280 for (const auto& it : object_logs_) {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100281 it.second.Undo(it.first);
282 }
283 object_logs_.clear();
284}
285
286void Transaction::UndoArrayModifications() {
287 // TODO we may not need to restore array allocated during this transaction. Or we could directly
288 // remove them from the heap.
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800289 for (const auto& it : array_logs_) {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100290 it.second.Undo(it.first);
291 }
292 array_logs_.clear();
293}
294
295void Transaction::UndoInternStringTableModifications() {
296 InternTable* const intern_table = Runtime::Current()->GetInternTable();
297 // We want to undo each operation from the most recent to the oldest. List has been filled so the
298 // most recent operation is at list begin so just have to iterate over it.
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800299 for (const InternStringLog& string_log : intern_string_logs_) {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100300 string_log.Undo(intern_table);
301 }
302 intern_string_logs_.clear();
303}
304
Mathieu Chartierbb816d62016-09-07 10:17:46 -0700305void Transaction::UndoResolveStringModifications() {
306 for (ResolveStringLog& string_log : resolve_string_logs_) {
307 string_log.Undo();
308 }
309 resolve_string_logs_.clear();
310}
311
Mathieu Chartierbb87e0f2015-04-03 11:21:55 -0700312void Transaction::VisitRoots(RootVisitor* visitor) {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100313 MutexLock mu(Thread::Current(), log_lock_);
Chang Xingcade5c32017-07-20 17:56:26 -0700314 visitor->VisitRoot(reinterpret_cast<mirror::Object**>(&root_), RootInfo(kRootUnknown));
Mathieu Chartierbb87e0f2015-04-03 11:21:55 -0700315 VisitObjectLogs(visitor);
316 VisitArrayLogs(visitor);
Mathieu Chartierbb816d62016-09-07 10:17:46 -0700317 VisitInternStringLogs(visitor);
318 VisitResolveStringLogs(visitor);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100319}
320
Mathieu Chartierbb87e0f2015-04-03 11:21:55 -0700321void Transaction::VisitObjectLogs(RootVisitor* visitor) {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100322 // List of moving roots.
323 typedef std::pair<mirror::Object*, mirror::Object*> ObjectPair;
324 std::list<ObjectPair> moving_roots;
325
326 // Visit roots.
Mathieu Chartier5f257b12017-02-03 14:47:36 -0800327 for (auto& it : object_logs_) {
Mathieu Chartierbb87e0f2015-04-03 11:21:55 -0700328 it.second.VisitRoots(visitor);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100329 mirror::Object* old_root = it.first;
Mathieu Chartier815873e2014-02-13 18:02:13 -0800330 mirror::Object* new_root = old_root;
Mathieu Chartierbb87e0f2015-04-03 11:21:55 -0700331 visitor->VisitRoot(&new_root, RootInfo(kRootUnknown));
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100332 if (new_root != old_root) {
333 moving_roots.push_back(std::make_pair(old_root, new_root));
334 }
335 }
336
337 // Update object logs with moving roots.
338 for (const ObjectPair& pair : moving_roots) {
339 mirror::Object* old_root = pair.first;
340 mirror::Object* new_root = pair.second;
341 auto old_root_it = object_logs_.find(old_root);
342 CHECK(old_root_it != object_logs_.end());
343 CHECK(object_logs_.find(new_root) == object_logs_.end());
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800344 object_logs_.emplace(new_root, std::move(old_root_it->second));
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100345 object_logs_.erase(old_root_it);
346 }
347}
348
Mathieu Chartierbb87e0f2015-04-03 11:21:55 -0700349void Transaction::VisitArrayLogs(RootVisitor* visitor) {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100350 // List of moving roots.
351 typedef std::pair<mirror::Array*, mirror::Array*> ArrayPair;
352 std::list<ArrayPair> moving_roots;
353
Mathieu Chartier5f257b12017-02-03 14:47:36 -0800354 for (auto& it : array_logs_) {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100355 mirror::Array* old_root = it.first;
Sebastien Hertzee1d79a2014-02-21 15:46:30 +0100356 CHECK(!old_root->IsObjectArray());
Mathieu Chartier815873e2014-02-13 18:02:13 -0800357 mirror::Array* new_root = old_root;
Mathieu Chartierbb87e0f2015-04-03 11:21:55 -0700358 visitor->VisitRoot(reinterpret_cast<mirror::Object**>(&new_root), RootInfo(kRootUnknown));
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100359 if (new_root != old_root) {
360 moving_roots.push_back(std::make_pair(old_root, new_root));
361 }
362 }
363
364 // Update array logs with moving roots.
365 for (const ArrayPair& pair : moving_roots) {
366 mirror::Array* old_root = pair.first;
367 mirror::Array* new_root = pair.second;
368 auto old_root_it = array_logs_.find(old_root);
369 CHECK(old_root_it != array_logs_.end());
370 CHECK(array_logs_.find(new_root) == array_logs_.end());
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800371 array_logs_.emplace(new_root, std::move(old_root_it->second));
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100372 array_logs_.erase(old_root_it);
373 }
374}
375
Mathieu Chartierbb816d62016-09-07 10:17:46 -0700376void Transaction::VisitInternStringLogs(RootVisitor* visitor) {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100377 for (InternStringLog& log : intern_string_logs_) {
Mathieu Chartierbb87e0f2015-04-03 11:21:55 -0700378 log.VisitRoots(visitor);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100379 }
380}
381
Mathieu Chartierbb816d62016-09-07 10:17:46 -0700382void Transaction::VisitResolveStringLogs(RootVisitor* visitor) {
383 for (ResolveStringLog& log : resolve_string_logs_) {
384 log.VisitRoots(visitor);
385 }
386}
387
Fred Shih37f05ef2014-07-16 18:38:08 -0700388void Transaction::ObjectLog::LogBooleanValue(MemberOffset offset, uint8_t value, bool is_volatile) {
389 LogValue(ObjectLog::kBoolean, offset, value, is_volatile);
390}
391
392void Transaction::ObjectLog::LogByteValue(MemberOffset offset, int8_t value, bool is_volatile) {
393 LogValue(ObjectLog::kByte, offset, value, is_volatile);
394}
395
396void Transaction::ObjectLog::LogCharValue(MemberOffset offset, uint16_t value, bool is_volatile) {
397 LogValue(ObjectLog::kChar, offset, value, is_volatile);
398}
399
400void Transaction::ObjectLog::LogShortValue(MemberOffset offset, int16_t value, bool is_volatile) {
401 LogValue(ObjectLog::kShort, offset, value, is_volatile);
402}
403
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100404void Transaction::ObjectLog::Log32BitsValue(MemberOffset offset, uint32_t value, bool is_volatile) {
Fred Shih37f05ef2014-07-16 18:38:08 -0700405 LogValue(ObjectLog::k32Bits, offset, value, is_volatile);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100406}
407
408void Transaction::ObjectLog::Log64BitsValue(MemberOffset offset, uint64_t value, bool is_volatile) {
Fred Shih37f05ef2014-07-16 18:38:08 -0700409 LogValue(ObjectLog::k64Bits, offset, value, is_volatile);
410}
411
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800412void Transaction::ObjectLog::LogReferenceValue(MemberOffset offset,
413 mirror::Object* obj,
414 bool is_volatile) {
Fred Shih37f05ef2014-07-16 18:38:08 -0700415 LogValue(ObjectLog::kReference, offset, reinterpret_cast<uintptr_t>(obj), is_volatile);
416}
417
418void Transaction::ObjectLog::LogValue(ObjectLog::FieldValueKind kind,
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800419 MemberOffset offset,
420 uint64_t value,
421 bool is_volatile) {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100422 auto it = field_values_.find(offset.Uint32Value());
423 if (it == field_values_.end()) {
424 ObjectLog::FieldValue field_value;
425 field_value.value = value;
426 field_value.is_volatile = is_volatile;
Fred Shih37f05ef2014-07-16 18:38:08 -0700427 field_value.kind = kind;
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800428 field_values_.emplace(offset.Uint32Value(), std::move(field_value));
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100429 }
430}
431
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800432void Transaction::ObjectLog::Undo(mirror::Object* obj) const {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100433 for (auto& it : field_values_) {
434 // Garbage collector needs to access object's class and array's length. So we don't rollback
435 // these values.
436 MemberOffset field_offset(it.first);
437 if (field_offset.Uint32Value() == mirror::Class::ClassOffset().Uint32Value()) {
438 // Skip Object::class field.
439 continue;
440 }
441 if (obj->IsArrayInstance() &&
442 field_offset.Uint32Value() == mirror::Array::LengthOffset().Uint32Value()) {
443 // Skip Array::length field.
444 continue;
445 }
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800446 const FieldValue& field_value = it.second;
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100447 UndoFieldWrite(obj, field_offset, field_value);
448 }
449}
450
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800451void Transaction::ObjectLog::UndoFieldWrite(mirror::Object* obj,
452 MemberOffset field_offset,
453 const FieldValue& field_value) const {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100454 // TODO We may want to abort a transaction while still being in transaction mode. In this case,
455 // we'd need to disable the check.
Chang Xing605fe242017-07-20 15:57:21 -0700456 constexpr bool kCheckTransaction = false;
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100457 switch (field_value.kind) {
Fred Shih37f05ef2014-07-16 18:38:08 -0700458 case kBoolean:
459 if (UNLIKELY(field_value.is_volatile)) {
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800460 obj->SetFieldBooleanVolatile<false, kCheckTransaction>(
461 field_offset,
462 static_cast<bool>(field_value.value));
Fred Shih37f05ef2014-07-16 18:38:08 -0700463 } else {
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800464 obj->SetFieldBoolean<false, kCheckTransaction>(
465 field_offset,
466 static_cast<bool>(field_value.value));
Fred Shih37f05ef2014-07-16 18:38:08 -0700467 }
468 break;
469 case kByte:
470 if (UNLIKELY(field_value.is_volatile)) {
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800471 obj->SetFieldByteVolatile<false, kCheckTransaction>(
472 field_offset,
473 static_cast<int8_t>(field_value.value));
Fred Shih37f05ef2014-07-16 18:38:08 -0700474 } else {
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800475 obj->SetFieldByte<false, kCheckTransaction>(
476 field_offset,
477 static_cast<int8_t>(field_value.value));
Fred Shih37f05ef2014-07-16 18:38:08 -0700478 }
479 break;
480 case kChar:
481 if (UNLIKELY(field_value.is_volatile)) {
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800482 obj->SetFieldCharVolatile<false, kCheckTransaction>(
483 field_offset,
484 static_cast<uint16_t>(field_value.value));
Fred Shih37f05ef2014-07-16 18:38:08 -0700485 } else {
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800486 obj->SetFieldChar<false, kCheckTransaction>(
487 field_offset,
488 static_cast<uint16_t>(field_value.value));
Fred Shih37f05ef2014-07-16 18:38:08 -0700489 }
490 break;
491 case kShort:
492 if (UNLIKELY(field_value.is_volatile)) {
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800493 obj->SetFieldShortVolatile<false, kCheckTransaction>(
494 field_offset,
495 static_cast<int16_t>(field_value.value));
Fred Shih37f05ef2014-07-16 18:38:08 -0700496 } else {
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800497 obj->SetFieldShort<false, kCheckTransaction>(
498 field_offset,
499 static_cast<int16_t>(field_value.value));
Fred Shih37f05ef2014-07-16 18:38:08 -0700500 }
501 break;
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100502 case k32Bits:
Ian Rogersb0fa5dc2014-04-28 16:47:08 -0700503 if (UNLIKELY(field_value.is_volatile)) {
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800504 obj->SetField32Volatile<false, kCheckTransaction>(
505 field_offset,
506 static_cast<uint32_t>(field_value.value));
Ian Rogersb0fa5dc2014-04-28 16:47:08 -0700507 } else {
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800508 obj->SetField32<false, kCheckTransaction>(
509 field_offset,
510 static_cast<uint32_t>(field_value.value));
Ian Rogersb0fa5dc2014-04-28 16:47:08 -0700511 }
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100512 break;
513 case k64Bits:
Ian Rogersb0fa5dc2014-04-28 16:47:08 -0700514 if (UNLIKELY(field_value.is_volatile)) {
515 obj->SetField64Volatile<false, kCheckTransaction>(field_offset, field_value.value);
516 } else {
517 obj->SetField64<false, kCheckTransaction>(field_offset, field_value.value);
518 }
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100519 break;
520 case kReference:
Ian Rogersb0fa5dc2014-04-28 16:47:08 -0700521 if (UNLIKELY(field_value.is_volatile)) {
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800522 obj->SetFieldObjectVolatile<false, kCheckTransaction>(
523 field_offset,
524 reinterpret_cast<mirror::Object*>(field_value.value));
Ian Rogersb0fa5dc2014-04-28 16:47:08 -0700525 } else {
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800526 obj->SetFieldObject<false, kCheckTransaction>(
527 field_offset,
528 reinterpret_cast<mirror::Object*>(field_value.value));
Ian Rogersb0fa5dc2014-04-28 16:47:08 -0700529 }
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100530 break;
531 default:
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700532 LOG(FATAL) << "Unknown value kind " << static_cast<int>(field_value.kind);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100533 break;
534 }
535}
536
Mathieu Chartierbb87e0f2015-04-03 11:21:55 -0700537void Transaction::ObjectLog::VisitRoots(RootVisitor* visitor) {
Mathieu Chartier5f257b12017-02-03 14:47:36 -0800538 for (auto& it : field_values_) {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100539 FieldValue& field_value = it.second;
540 if (field_value.kind == ObjectLog::kReference) {
Mathieu Chartierbb87e0f2015-04-03 11:21:55 -0700541 visitor->VisitRootIfNonNull(reinterpret_cast<mirror::Object**>(&field_value.value),
542 RootInfo(kRootUnknown));
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100543 }
544 }
545}
546
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800547void Transaction::InternStringLog::Undo(InternTable* intern_table) const {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100548 DCHECK(intern_table != nullptr);
549 switch (string_op_) {
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700550 case InternStringLog::kInsert: {
551 switch (string_kind_) {
552 case InternStringLog::kStrongString:
Mathieu Chartier9e868092016-10-31 14:58:04 -0700553 intern_table->RemoveStrongFromTransaction(str_.Read());
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700554 break;
555 case InternStringLog::kWeakString:
Mathieu Chartier9e868092016-10-31 14:58:04 -0700556 intern_table->RemoveWeakFromTransaction(str_.Read());
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700557 break;
558 default:
559 LOG(FATAL) << "Unknown interned string kind";
560 break;
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100561 }
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700562 break;
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100563 }
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700564 case InternStringLog::kRemove: {
565 switch (string_kind_) {
566 case InternStringLog::kStrongString:
Mathieu Chartier9e868092016-10-31 14:58:04 -0700567 intern_table->InsertStrongFromTransaction(str_.Read());
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700568 break;
569 case InternStringLog::kWeakString:
Mathieu Chartier9e868092016-10-31 14:58:04 -0700570 intern_table->InsertWeakFromTransaction(str_.Read());
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700571 break;
572 default:
573 LOG(FATAL) << "Unknown interned string kind";
574 break;
575 }
576 break;
577 }
578 default:
579 LOG(FATAL) << "Unknown interned string op";
580 break;
581 }
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100582}
583
Mathieu Chartierbb87e0f2015-04-03 11:21:55 -0700584void Transaction::InternStringLog::VisitRoots(RootVisitor* visitor) {
Mathieu Chartier9e868092016-10-31 14:58:04 -0700585 str_.VisitRoot(visitor, RootInfo(kRootInternedString));
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100586}
587
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800588void Transaction::ResolveStringLog::Undo() const {
Mathieu Chartierbb816d62016-09-07 10:17:46 -0700589 dex_cache_.Read()->ClearString(string_idx_);
590}
591
Mathieu Chartier9e868092016-10-31 14:58:04 -0700592Transaction::ResolveStringLog::ResolveStringLog(ObjPtr<mirror::DexCache> dex_cache,
Andreas Gampe8a0128a2016-11-28 07:38:35 -0800593 dex::StringIndex string_idx)
Mathieu Chartierbb816d62016-09-07 10:17:46 -0700594 : dex_cache_(dex_cache),
595 string_idx_(string_idx) {
596 DCHECK(dex_cache != nullptr);
Andreas Gampe8a0128a2016-11-28 07:38:35 -0800597 DCHECK_LT(string_idx_.index_, dex_cache->GetDexFile()->NumStringIds());
Mathieu Chartierbb816d62016-09-07 10:17:46 -0700598}
599
600void Transaction::ResolveStringLog::VisitRoots(RootVisitor* visitor) {
601 dex_cache_.VisitRoot(visitor, RootInfo(kRootVMInternal));
602}
603
Mathieu Chartier9e868092016-10-31 14:58:04 -0700604Transaction::InternStringLog::InternStringLog(ObjPtr<mirror::String> s,
605 StringKind kind,
606 StringOp op)
607 : str_(s),
608 string_kind_(kind),
609 string_op_(op) {
610 DCHECK(s != nullptr);
611}
612
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100613void Transaction::ArrayLog::LogValue(size_t index, uint64_t value) {
614 auto it = array_values_.find(index);
615 if (it == array_values_.end()) {
616 array_values_.insert(std::make_pair(index, value));
617 }
618}
619
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800620void Transaction::ArrayLog::Undo(mirror::Array* array) const {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100621 DCHECK(array != nullptr);
622 DCHECK(array->IsArrayInstance());
623 Primitive::Type type = array->GetClass()->GetComponentType()->GetPrimitiveType();
624 for (auto it : array_values_) {
625 UndoArrayWrite(array, type, it.first, it.second);
626 }
627}
628
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800629void Transaction::ArrayLog::UndoArrayWrite(mirror::Array* array,
630 Primitive::Type array_type,
631 size_t index,
632 uint64_t value) const {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100633 // TODO We may want to abort a transaction while still being in transaction mode. In this case,
634 // we'd need to disable the check.
Chang Xing605fe242017-07-20 15:57:21 -0700635 constexpr bool kCheckTransaction = false;
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100636 switch (array_type) {
637 case Primitive::kPrimBoolean:
Chang Xing605fe242017-07-20 15:57:21 -0700638 array->AsBooleanArray()->SetWithoutChecks<false, kCheckTransaction>(
639 index, static_cast<uint8_t>(value));
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100640 break;
641 case Primitive::kPrimByte:
Chang Xing605fe242017-07-20 15:57:21 -0700642 array->AsByteArray()->SetWithoutChecks<false, kCheckTransaction>(
643 index, static_cast<int8_t>(value));
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100644 break;
645 case Primitive::kPrimChar:
Chang Xing605fe242017-07-20 15:57:21 -0700646 array->AsCharArray()->SetWithoutChecks<false, kCheckTransaction>(
647 index, static_cast<uint16_t>(value));
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100648 break;
649 case Primitive::kPrimShort:
Chang Xing605fe242017-07-20 15:57:21 -0700650 array->AsShortArray()->SetWithoutChecks<false, kCheckTransaction>(
651 index, static_cast<int16_t>(value));
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100652 break;
653 case Primitive::kPrimInt:
Chang Xing605fe242017-07-20 15:57:21 -0700654 array->AsIntArray()->SetWithoutChecks<false, kCheckTransaction>(
655 index, static_cast<int32_t>(value));
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100656 break;
657 case Primitive::kPrimFloat:
Chang Xing605fe242017-07-20 15:57:21 -0700658 array->AsFloatArray()->SetWithoutChecks<false, kCheckTransaction>(
659 index, static_cast<float>(value));
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100660 break;
661 case Primitive::kPrimLong:
Chang Xing605fe242017-07-20 15:57:21 -0700662 array->AsLongArray()->SetWithoutChecks<false, kCheckTransaction>(
663 index, static_cast<int64_t>(value));
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100664 break;
665 case Primitive::kPrimDouble:
Chang Xing605fe242017-07-20 15:57:21 -0700666 array->AsDoubleArray()->SetWithoutChecks<false, kCheckTransaction>(
667 index, static_cast<double>(value));
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100668 break;
Sebastien Hertzee1d79a2014-02-21 15:46:30 +0100669 case Primitive::kPrimNot:
670 LOG(FATAL) << "ObjectArray should be treated as Object";
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100671 break;
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100672 default:
673 LOG(FATAL) << "Unsupported type " << array_type;
674 }
675}
676
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100677} // namespace art