blob: 56ff0a13ac36420141205c987a1b19659ab8e9c1 [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"
22#include "intern_table.h"
Mathieu Chartiere401d142015-04-22 13:56:20 -070023#include "mirror/class-inl.h"
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +010024#include "mirror/object-inl.h"
25#include "mirror/object_array-inl.h"
26
27#include <list>
28
29namespace art {
30
31// TODO: remove (only used for debugging purpose).
32static constexpr bool kEnableTransactionStats = false;
33
Sebastien Hertz1c80bec2015-02-03 11:58:06 +010034Transaction::Transaction()
35 : log_lock_("transaction log lock", kTransactionLogLock), aborted_(false) {
Mathieu Chartiere5f13e52015-02-24 09:37:21 -080036 CHECK(Runtime::Current()->IsAotCompiler());
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +010037}
38
39Transaction::~Transaction() {
40 if (kEnableTransactionStats) {
41 MutexLock mu(Thread::Current(), log_lock_);
42 size_t objects_count = object_logs_.size();
43 size_t field_values_count = 0;
Mathieu Chartier38e954c2017-02-03 16:06:35 -080044 for (const auto& it : object_logs_) {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +010045 field_values_count += it.second.Size();
46 }
47 size_t array_count = array_logs_.size();
48 size_t array_values_count = 0;
Mathieu Chartier38e954c2017-02-03 16:06:35 -080049 for (const auto& it : array_logs_) {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +010050 array_values_count += it.second.Size();
51 }
Mathieu Chartierbb816d62016-09-07 10:17:46 -070052 size_t intern_string_count = intern_string_logs_.size();
53 size_t resolve_string_count = resolve_string_logs_.size();
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +010054 LOG(INFO) << "Transaction::~Transaction"
55 << ": objects_count=" << objects_count
56 << ", field_values_count=" << field_values_count
57 << ", array_count=" << array_count
58 << ", array_values_count=" << array_values_count
Mathieu Chartierbb816d62016-09-07 10:17:46 -070059 << ", intern_string_count=" << intern_string_count
60 << ", resolve_string_count=" << resolve_string_count;
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +010061 }
62}
63
Sebastien Hertz1c80bec2015-02-03 11:58:06 +010064void Transaction::Abort(const std::string& abort_message) {
65 MutexLock mu(Thread::Current(), log_lock_);
Sebastien Hertz2fd7e692015-04-02 11:11:19 +020066 // We may abort more than once if the exception thrown at the time of the
67 // previous abort has been caught during execution of a class initializer.
Sebastien Hertz1c80bec2015-02-03 11:58:06 +010068 // We just keep the message of the first abort because it will cause the
69 // transaction to be rolled back anyway.
70 if (!aborted_) {
71 aborted_ = true;
72 abort_message_ = abort_message;
73 }
74}
75
Sebastien Hertzb81e1cd2015-04-28 12:31:41 +020076void Transaction::ThrowAbortError(Thread* self, const std::string* abort_message) {
77 const bool rethrow = (abort_message == nullptr);
Sebastien Hertzbd9cf9f2015-03-03 12:16:13 +010078 if (kIsDebugBuild && rethrow) {
Sebastien Hertz2fd7e692015-04-02 11:11:19 +020079 CHECK(IsAborted()) << "Rethrow " << Transaction::kAbortExceptionDescriptor
80 << " while transaction is not aborted";
Sebastien Hertzbd9cf9f2015-03-03 12:16:13 +010081 }
Sebastien Hertzb81e1cd2015-04-28 12:31:41 +020082 if (rethrow) {
83 // Rethrow an exception with the earlier abort message stored in the transaction.
84 self->ThrowNewWrappedException(Transaction::kAbortExceptionSignature,
85 GetAbortMessage().c_str());
86 } else {
87 // Throw an exception with the given abort message.
88 self->ThrowNewWrappedException(Transaction::kAbortExceptionSignature,
89 abort_message->c_str());
90 }
Sebastien Hertz1c80bec2015-02-03 11:58:06 +010091}
92
93bool Transaction::IsAborted() {
94 MutexLock mu(Thread::Current(), log_lock_);
95 return aborted_;
96}
97
98const std::string& Transaction::GetAbortMessage() {
99 MutexLock mu(Thread::Current(), log_lock_);
100 return abort_message_;
101}
102
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800103void Transaction::RecordWriteFieldBoolean(mirror::Object* obj,
104 MemberOffset field_offset,
105 uint8_t value,
106 bool is_volatile) {
Fred Shih37f05ef2014-07-16 18:38:08 -0700107 DCHECK(obj != nullptr);
108 MutexLock mu(Thread::Current(), log_lock_);
109 ObjectLog& object_log = object_logs_[obj];
110 object_log.LogBooleanValue(field_offset, value, is_volatile);
111}
112
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800113void Transaction::RecordWriteFieldByte(mirror::Object* obj,
114 MemberOffset field_offset,
115 int8_t value,
116 bool is_volatile) {
Fred Shih37f05ef2014-07-16 18:38:08 -0700117 DCHECK(obj != nullptr);
118 MutexLock mu(Thread::Current(), log_lock_);
119 ObjectLog& object_log = object_logs_[obj];
120 object_log.LogByteValue(field_offset, value, is_volatile);
121}
122
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800123void Transaction::RecordWriteFieldChar(mirror::Object* obj,
124 MemberOffset field_offset,
125 uint16_t value,
126 bool is_volatile) {
Fred Shih37f05ef2014-07-16 18:38:08 -0700127 DCHECK(obj != nullptr);
128 MutexLock mu(Thread::Current(), log_lock_);
129 ObjectLog& object_log = object_logs_[obj];
130 object_log.LogCharValue(field_offset, value, is_volatile);
131}
132
133
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800134void Transaction::RecordWriteFieldShort(mirror::Object* obj,
135 MemberOffset field_offset,
136 int16_t value,
137 bool is_volatile) {
Fred Shih37f05ef2014-07-16 18:38:08 -0700138 DCHECK(obj != nullptr);
139 MutexLock mu(Thread::Current(), log_lock_);
140 ObjectLog& object_log = object_logs_[obj];
141 object_log.LogShortValue(field_offset, value, is_volatile);
142}
143
144
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800145void Transaction::RecordWriteField32(mirror::Object* obj,
146 MemberOffset field_offset,
147 uint32_t value,
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100148 bool is_volatile) {
149 DCHECK(obj != nullptr);
150 MutexLock mu(Thread::Current(), log_lock_);
151 ObjectLog& object_log = object_logs_[obj];
152 object_log.Log32BitsValue(field_offset, value, is_volatile);
153}
154
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800155void Transaction::RecordWriteField64(mirror::Object* obj,
156 MemberOffset field_offset,
157 uint64_t value,
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100158 bool is_volatile) {
159 DCHECK(obj != nullptr);
160 MutexLock mu(Thread::Current(), log_lock_);
161 ObjectLog& object_log = object_logs_[obj];
162 object_log.Log64BitsValue(field_offset, value, is_volatile);
163}
164
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800165void Transaction::RecordWriteFieldReference(mirror::Object* obj,
166 MemberOffset field_offset,
167 mirror::Object* value,
168 bool is_volatile) {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100169 DCHECK(obj != nullptr);
170 MutexLock mu(Thread::Current(), log_lock_);
171 ObjectLog& object_log = object_logs_[obj];
172 object_log.LogReferenceValue(field_offset, value, is_volatile);
173}
174
175void Transaction::RecordWriteArray(mirror::Array* array, size_t index, uint64_t value) {
176 DCHECK(array != nullptr);
177 DCHECK(array->IsArrayInstance());
Sebastien Hertzee1d79a2014-02-21 15:46:30 +0100178 DCHECK(!array->IsObjectArray());
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100179 MutexLock mu(Thread::Current(), log_lock_);
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800180 auto it = array_logs_.find(array);
181 if (it == array_logs_.end()) {
182 ArrayLog log;
183 it = array_logs_.emplace(array, std::move(log)).first;
184 }
185 it->second.LogValue(index, value);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100186}
187
Andreas Gampe8a0128a2016-11-28 07:38:35 -0800188void Transaction::RecordResolveString(ObjPtr<mirror::DexCache> dex_cache,
189 dex::StringIndex string_idx) {
Mathieu Chartierbb816d62016-09-07 10:17:46 -0700190 DCHECK(dex_cache != nullptr);
Andreas Gampe8a0128a2016-11-28 07:38:35 -0800191 DCHECK_LT(string_idx.index_, dex_cache->GetDexFile()->NumStringIds());
Mathieu Chartierbb816d62016-09-07 10:17:46 -0700192 MutexLock mu(Thread::Current(), log_lock_);
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800193 resolve_string_logs_.emplace_back(dex_cache, string_idx);
Mathieu Chartierbb816d62016-09-07 10:17:46 -0700194}
195
Mathieu Chartier9e868092016-10-31 14:58:04 -0700196void Transaction::RecordStrongStringInsertion(ObjPtr<mirror::String> s) {
Mathieu Chartiercdfd39f2014-08-29 18:16:58 -0700197 InternStringLog log(s, InternStringLog::kStrongString, InternStringLog::kInsert);
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800198 LogInternedString(std::move(log));
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100199}
200
Mathieu Chartier9e868092016-10-31 14:58:04 -0700201void Transaction::RecordWeakStringInsertion(ObjPtr<mirror::String> s) {
Mathieu Chartiercdfd39f2014-08-29 18:16:58 -0700202 InternStringLog log(s, InternStringLog::kWeakString, InternStringLog::kInsert);
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800203 LogInternedString(std::move(log));
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100204}
205
Mathieu Chartier9e868092016-10-31 14:58:04 -0700206void Transaction::RecordStrongStringRemoval(ObjPtr<mirror::String> s) {
Mathieu Chartiercdfd39f2014-08-29 18:16:58 -0700207 InternStringLog log(s, InternStringLog::kStrongString, InternStringLog::kRemove);
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800208 LogInternedString(std::move(log));
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100209}
210
Mathieu Chartier9e868092016-10-31 14:58:04 -0700211void Transaction::RecordWeakStringRemoval(ObjPtr<mirror::String> s) {
Mathieu Chartiercdfd39f2014-08-29 18:16:58 -0700212 InternStringLog log(s, InternStringLog::kWeakString, InternStringLog::kRemove);
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800213 LogInternedString(std::move(log));
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100214}
215
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800216void Transaction::LogInternedString(InternStringLog&& log) {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100217 Locks::intern_table_lock_->AssertExclusiveHeld(Thread::Current());
218 MutexLock mu(Thread::Current(), log_lock_);
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800219 intern_string_logs_.push_front(std::move(log));
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100220}
221
Sebastien Hertz1c80bec2015-02-03 11:58:06 +0100222void Transaction::Rollback() {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100223 CHECK(!Runtime::Current()->IsActiveTransaction());
224 Thread* self = Thread::Current();
225 self->AssertNoPendingException();
226 MutexLock mu1(self, *Locks::intern_table_lock_);
227 MutexLock mu2(self, log_lock_);
228 UndoObjectModifications();
229 UndoArrayModifications();
230 UndoInternStringTableModifications();
Mathieu Chartierbb816d62016-09-07 10:17:46 -0700231 UndoResolveStringModifications();
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100232}
233
234void Transaction::UndoObjectModifications() {
235 // TODO we may not need to restore objects allocated during this transaction. Or we could directly
236 // remove them from the heap.
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800237 for (const auto& it : object_logs_) {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100238 it.second.Undo(it.first);
239 }
240 object_logs_.clear();
241}
242
243void Transaction::UndoArrayModifications() {
244 // TODO we may not need to restore array allocated during this transaction. Or we could directly
245 // remove them from the heap.
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800246 for (const auto& it : array_logs_) {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100247 it.second.Undo(it.first);
248 }
249 array_logs_.clear();
250}
251
252void Transaction::UndoInternStringTableModifications() {
253 InternTable* const intern_table = Runtime::Current()->GetInternTable();
254 // We want to undo each operation from the most recent to the oldest. List has been filled so the
255 // most recent operation is at list begin so just have to iterate over it.
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800256 for (const InternStringLog& string_log : intern_string_logs_) {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100257 string_log.Undo(intern_table);
258 }
259 intern_string_logs_.clear();
260}
261
Mathieu Chartierbb816d62016-09-07 10:17:46 -0700262void Transaction::UndoResolveStringModifications() {
263 for (ResolveStringLog& string_log : resolve_string_logs_) {
264 string_log.Undo();
265 }
266 resolve_string_logs_.clear();
267}
268
Mathieu Chartierbb87e0f2015-04-03 11:21:55 -0700269void Transaction::VisitRoots(RootVisitor* visitor) {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100270 MutexLock mu(Thread::Current(), log_lock_);
Mathieu Chartierbb87e0f2015-04-03 11:21:55 -0700271 VisitObjectLogs(visitor);
272 VisitArrayLogs(visitor);
Mathieu Chartierbb816d62016-09-07 10:17:46 -0700273 VisitInternStringLogs(visitor);
274 VisitResolveStringLogs(visitor);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100275}
276
Mathieu Chartierbb87e0f2015-04-03 11:21:55 -0700277void Transaction::VisitObjectLogs(RootVisitor* visitor) {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100278 // List of moving roots.
279 typedef std::pair<mirror::Object*, mirror::Object*> ObjectPair;
280 std::list<ObjectPair> moving_roots;
281
282 // Visit roots.
Mathieu Chartier5f257b12017-02-03 14:47:36 -0800283 for (auto& it : object_logs_) {
Mathieu Chartierbb87e0f2015-04-03 11:21:55 -0700284 it.second.VisitRoots(visitor);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100285 mirror::Object* old_root = it.first;
Mathieu Chartier815873e2014-02-13 18:02:13 -0800286 mirror::Object* new_root = old_root;
Mathieu Chartierbb87e0f2015-04-03 11:21:55 -0700287 visitor->VisitRoot(&new_root, RootInfo(kRootUnknown));
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100288 if (new_root != old_root) {
289 moving_roots.push_back(std::make_pair(old_root, new_root));
290 }
291 }
292
293 // Update object logs with moving roots.
294 for (const ObjectPair& pair : moving_roots) {
295 mirror::Object* old_root = pair.first;
296 mirror::Object* new_root = pair.second;
297 auto old_root_it = object_logs_.find(old_root);
298 CHECK(old_root_it != object_logs_.end());
299 CHECK(object_logs_.find(new_root) == object_logs_.end());
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800300 object_logs_.emplace(new_root, std::move(old_root_it->second));
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100301 object_logs_.erase(old_root_it);
302 }
303}
304
Mathieu Chartierbb87e0f2015-04-03 11:21:55 -0700305void Transaction::VisitArrayLogs(RootVisitor* visitor) {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100306 // List of moving roots.
307 typedef std::pair<mirror::Array*, mirror::Array*> ArrayPair;
308 std::list<ArrayPair> moving_roots;
309
Mathieu Chartier5f257b12017-02-03 14:47:36 -0800310 for (auto& it : array_logs_) {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100311 mirror::Array* old_root = it.first;
Sebastien Hertzee1d79a2014-02-21 15:46:30 +0100312 CHECK(!old_root->IsObjectArray());
Mathieu Chartier815873e2014-02-13 18:02:13 -0800313 mirror::Array* new_root = old_root;
Mathieu Chartierbb87e0f2015-04-03 11:21:55 -0700314 visitor->VisitRoot(reinterpret_cast<mirror::Object**>(&new_root), RootInfo(kRootUnknown));
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100315 if (new_root != old_root) {
316 moving_roots.push_back(std::make_pair(old_root, new_root));
317 }
318 }
319
320 // Update array logs with moving roots.
321 for (const ArrayPair& pair : moving_roots) {
322 mirror::Array* old_root = pair.first;
323 mirror::Array* new_root = pair.second;
324 auto old_root_it = array_logs_.find(old_root);
325 CHECK(old_root_it != array_logs_.end());
326 CHECK(array_logs_.find(new_root) == array_logs_.end());
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800327 array_logs_.emplace(new_root, std::move(old_root_it->second));
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100328 array_logs_.erase(old_root_it);
329 }
330}
331
Mathieu Chartierbb816d62016-09-07 10:17:46 -0700332void Transaction::VisitInternStringLogs(RootVisitor* visitor) {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100333 for (InternStringLog& log : intern_string_logs_) {
Mathieu Chartierbb87e0f2015-04-03 11:21:55 -0700334 log.VisitRoots(visitor);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100335 }
336}
337
Mathieu Chartierbb816d62016-09-07 10:17:46 -0700338void Transaction::VisitResolveStringLogs(RootVisitor* visitor) {
339 for (ResolveStringLog& log : resolve_string_logs_) {
340 log.VisitRoots(visitor);
341 }
342}
343
Fred Shih37f05ef2014-07-16 18:38:08 -0700344void Transaction::ObjectLog::LogBooleanValue(MemberOffset offset, uint8_t value, bool is_volatile) {
345 LogValue(ObjectLog::kBoolean, offset, value, is_volatile);
346}
347
348void Transaction::ObjectLog::LogByteValue(MemberOffset offset, int8_t value, bool is_volatile) {
349 LogValue(ObjectLog::kByte, offset, value, is_volatile);
350}
351
352void Transaction::ObjectLog::LogCharValue(MemberOffset offset, uint16_t value, bool is_volatile) {
353 LogValue(ObjectLog::kChar, offset, value, is_volatile);
354}
355
356void Transaction::ObjectLog::LogShortValue(MemberOffset offset, int16_t value, bool is_volatile) {
357 LogValue(ObjectLog::kShort, offset, value, is_volatile);
358}
359
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100360void Transaction::ObjectLog::Log32BitsValue(MemberOffset offset, uint32_t value, bool is_volatile) {
Fred Shih37f05ef2014-07-16 18:38:08 -0700361 LogValue(ObjectLog::k32Bits, offset, value, is_volatile);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100362}
363
364void Transaction::ObjectLog::Log64BitsValue(MemberOffset offset, uint64_t value, bool is_volatile) {
Fred Shih37f05ef2014-07-16 18:38:08 -0700365 LogValue(ObjectLog::k64Bits, offset, value, is_volatile);
366}
367
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800368void Transaction::ObjectLog::LogReferenceValue(MemberOffset offset,
369 mirror::Object* obj,
370 bool is_volatile) {
Fred Shih37f05ef2014-07-16 18:38:08 -0700371 LogValue(ObjectLog::kReference, offset, reinterpret_cast<uintptr_t>(obj), is_volatile);
372}
373
374void Transaction::ObjectLog::LogValue(ObjectLog::FieldValueKind kind,
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800375 MemberOffset offset,
376 uint64_t value,
377 bool is_volatile) {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100378 auto it = field_values_.find(offset.Uint32Value());
379 if (it == field_values_.end()) {
380 ObjectLog::FieldValue field_value;
381 field_value.value = value;
382 field_value.is_volatile = is_volatile;
Fred Shih37f05ef2014-07-16 18:38:08 -0700383 field_value.kind = kind;
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800384 field_values_.emplace(offset.Uint32Value(), std::move(field_value));
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100385 }
386}
387
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800388void Transaction::ObjectLog::Undo(mirror::Object* obj) const {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100389 for (auto& it : field_values_) {
390 // Garbage collector needs to access object's class and array's length. So we don't rollback
391 // these values.
392 MemberOffset field_offset(it.first);
393 if (field_offset.Uint32Value() == mirror::Class::ClassOffset().Uint32Value()) {
394 // Skip Object::class field.
395 continue;
396 }
397 if (obj->IsArrayInstance() &&
398 field_offset.Uint32Value() == mirror::Array::LengthOffset().Uint32Value()) {
399 // Skip Array::length field.
400 continue;
401 }
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800402 const FieldValue& field_value = it.second;
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100403 UndoFieldWrite(obj, field_offset, field_value);
404 }
405}
406
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800407void Transaction::ObjectLog::UndoFieldWrite(mirror::Object* obj,
408 MemberOffset field_offset,
409 const FieldValue& field_value) const {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100410 // TODO We may want to abort a transaction while still being in transaction mode. In this case,
411 // we'd need to disable the check.
412 constexpr bool kCheckTransaction = true;
413 switch (field_value.kind) {
Fred Shih37f05ef2014-07-16 18:38:08 -0700414 case kBoolean:
415 if (UNLIKELY(field_value.is_volatile)) {
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800416 obj->SetFieldBooleanVolatile<false, kCheckTransaction>(
417 field_offset,
418 static_cast<bool>(field_value.value));
Fred Shih37f05ef2014-07-16 18:38:08 -0700419 } else {
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800420 obj->SetFieldBoolean<false, kCheckTransaction>(
421 field_offset,
422 static_cast<bool>(field_value.value));
Fred Shih37f05ef2014-07-16 18:38:08 -0700423 }
424 break;
425 case kByte:
426 if (UNLIKELY(field_value.is_volatile)) {
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800427 obj->SetFieldByteVolatile<false, kCheckTransaction>(
428 field_offset,
429 static_cast<int8_t>(field_value.value));
Fred Shih37f05ef2014-07-16 18:38:08 -0700430 } else {
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800431 obj->SetFieldByte<false, kCheckTransaction>(
432 field_offset,
433 static_cast<int8_t>(field_value.value));
Fred Shih37f05ef2014-07-16 18:38:08 -0700434 }
435 break;
436 case kChar:
437 if (UNLIKELY(field_value.is_volatile)) {
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800438 obj->SetFieldCharVolatile<false, kCheckTransaction>(
439 field_offset,
440 static_cast<uint16_t>(field_value.value));
Fred Shih37f05ef2014-07-16 18:38:08 -0700441 } else {
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800442 obj->SetFieldChar<false, kCheckTransaction>(
443 field_offset,
444 static_cast<uint16_t>(field_value.value));
Fred Shih37f05ef2014-07-16 18:38:08 -0700445 }
446 break;
447 case kShort:
448 if (UNLIKELY(field_value.is_volatile)) {
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800449 obj->SetFieldShortVolatile<false, kCheckTransaction>(
450 field_offset,
451 static_cast<int16_t>(field_value.value));
Fred Shih37f05ef2014-07-16 18:38:08 -0700452 } else {
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800453 obj->SetFieldShort<false, kCheckTransaction>(
454 field_offset,
455 static_cast<int16_t>(field_value.value));
Fred Shih37f05ef2014-07-16 18:38:08 -0700456 }
457 break;
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100458 case k32Bits:
Ian Rogersb0fa5dc2014-04-28 16:47:08 -0700459 if (UNLIKELY(field_value.is_volatile)) {
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800460 obj->SetField32Volatile<false, kCheckTransaction>(
461 field_offset,
462 static_cast<uint32_t>(field_value.value));
Ian Rogersb0fa5dc2014-04-28 16:47:08 -0700463 } else {
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800464 obj->SetField32<false, kCheckTransaction>(
465 field_offset,
466 static_cast<uint32_t>(field_value.value));
Ian Rogersb0fa5dc2014-04-28 16:47:08 -0700467 }
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100468 break;
469 case k64Bits:
Ian Rogersb0fa5dc2014-04-28 16:47:08 -0700470 if (UNLIKELY(field_value.is_volatile)) {
471 obj->SetField64Volatile<false, kCheckTransaction>(field_offset, field_value.value);
472 } else {
473 obj->SetField64<false, kCheckTransaction>(field_offset, field_value.value);
474 }
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100475 break;
476 case kReference:
Ian Rogersb0fa5dc2014-04-28 16:47:08 -0700477 if (UNLIKELY(field_value.is_volatile)) {
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800478 obj->SetFieldObjectVolatile<false, kCheckTransaction>(
479 field_offset,
480 reinterpret_cast<mirror::Object*>(field_value.value));
Ian Rogersb0fa5dc2014-04-28 16:47:08 -0700481 } else {
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800482 obj->SetFieldObject<false, kCheckTransaction>(
483 field_offset,
484 reinterpret_cast<mirror::Object*>(field_value.value));
Ian Rogersb0fa5dc2014-04-28 16:47:08 -0700485 }
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100486 break;
487 default:
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700488 LOG(FATAL) << "Unknown value kind " << static_cast<int>(field_value.kind);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100489 break;
490 }
491}
492
Mathieu Chartierbb87e0f2015-04-03 11:21:55 -0700493void Transaction::ObjectLog::VisitRoots(RootVisitor* visitor) {
Mathieu Chartier5f257b12017-02-03 14:47:36 -0800494 for (auto& it : field_values_) {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100495 FieldValue& field_value = it.second;
496 if (field_value.kind == ObjectLog::kReference) {
Mathieu Chartierbb87e0f2015-04-03 11:21:55 -0700497 visitor->VisitRootIfNonNull(reinterpret_cast<mirror::Object**>(&field_value.value),
498 RootInfo(kRootUnknown));
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100499 }
500 }
501}
502
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800503void Transaction::InternStringLog::Undo(InternTable* intern_table) const {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100504 DCHECK(intern_table != nullptr);
505 switch (string_op_) {
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700506 case InternStringLog::kInsert: {
507 switch (string_kind_) {
508 case InternStringLog::kStrongString:
Mathieu Chartier9e868092016-10-31 14:58:04 -0700509 intern_table->RemoveStrongFromTransaction(str_.Read());
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700510 break;
511 case InternStringLog::kWeakString:
Mathieu Chartier9e868092016-10-31 14:58:04 -0700512 intern_table->RemoveWeakFromTransaction(str_.Read());
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700513 break;
514 default:
515 LOG(FATAL) << "Unknown interned string kind";
516 break;
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100517 }
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700518 break;
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100519 }
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700520 case InternStringLog::kRemove: {
521 switch (string_kind_) {
522 case InternStringLog::kStrongString:
Mathieu Chartier9e868092016-10-31 14:58:04 -0700523 intern_table->InsertStrongFromTransaction(str_.Read());
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700524 break;
525 case InternStringLog::kWeakString:
Mathieu Chartier9e868092016-10-31 14:58:04 -0700526 intern_table->InsertWeakFromTransaction(str_.Read());
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700527 break;
528 default:
529 LOG(FATAL) << "Unknown interned string kind";
530 break;
531 }
532 break;
533 }
534 default:
535 LOG(FATAL) << "Unknown interned string op";
536 break;
537 }
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100538}
539
Mathieu Chartierbb87e0f2015-04-03 11:21:55 -0700540void Transaction::InternStringLog::VisitRoots(RootVisitor* visitor) {
Mathieu Chartier9e868092016-10-31 14:58:04 -0700541 str_.VisitRoot(visitor, RootInfo(kRootInternedString));
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100542}
543
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800544void Transaction::ResolveStringLog::Undo() const {
Mathieu Chartierbb816d62016-09-07 10:17:46 -0700545 dex_cache_.Read()->ClearString(string_idx_);
546}
547
Mathieu Chartier9e868092016-10-31 14:58:04 -0700548Transaction::ResolveStringLog::ResolveStringLog(ObjPtr<mirror::DexCache> dex_cache,
Andreas Gampe8a0128a2016-11-28 07:38:35 -0800549 dex::StringIndex string_idx)
Mathieu Chartierbb816d62016-09-07 10:17:46 -0700550 : dex_cache_(dex_cache),
551 string_idx_(string_idx) {
552 DCHECK(dex_cache != nullptr);
Andreas Gampe8a0128a2016-11-28 07:38:35 -0800553 DCHECK_LT(string_idx_.index_, dex_cache->GetDexFile()->NumStringIds());
Mathieu Chartierbb816d62016-09-07 10:17:46 -0700554}
555
556void Transaction::ResolveStringLog::VisitRoots(RootVisitor* visitor) {
557 dex_cache_.VisitRoot(visitor, RootInfo(kRootVMInternal));
558}
559
Mathieu Chartier9e868092016-10-31 14:58:04 -0700560Transaction::InternStringLog::InternStringLog(ObjPtr<mirror::String> s,
561 StringKind kind,
562 StringOp op)
563 : str_(s),
564 string_kind_(kind),
565 string_op_(op) {
566 DCHECK(s != nullptr);
567}
568
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100569void Transaction::ArrayLog::LogValue(size_t index, uint64_t value) {
570 auto it = array_values_.find(index);
571 if (it == array_values_.end()) {
572 array_values_.insert(std::make_pair(index, value));
573 }
574}
575
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800576void Transaction::ArrayLog::Undo(mirror::Array* array) const {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100577 DCHECK(array != nullptr);
578 DCHECK(array->IsArrayInstance());
579 Primitive::Type type = array->GetClass()->GetComponentType()->GetPrimitiveType();
580 for (auto it : array_values_) {
581 UndoArrayWrite(array, type, it.first, it.second);
582 }
583}
584
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800585void Transaction::ArrayLog::UndoArrayWrite(mirror::Array* array,
586 Primitive::Type array_type,
587 size_t index,
588 uint64_t value) const {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100589 // TODO We may want to abort a transaction while still being in transaction mode. In this case,
590 // we'd need to disable the check.
591 switch (array_type) {
592 case Primitive::kPrimBoolean:
593 array->AsBooleanArray()->SetWithoutChecks<false>(index, static_cast<uint8_t>(value));
594 break;
595 case Primitive::kPrimByte:
596 array->AsByteArray()->SetWithoutChecks<false>(index, static_cast<int8_t>(value));
597 break;
598 case Primitive::kPrimChar:
599 array->AsCharArray()->SetWithoutChecks<false>(index, static_cast<uint16_t>(value));
600 break;
601 case Primitive::kPrimShort:
602 array->AsShortArray()->SetWithoutChecks<false>(index, static_cast<int16_t>(value));
603 break;
604 case Primitive::kPrimInt:
605 array->AsIntArray()->SetWithoutChecks<false>(index, static_cast<int32_t>(value));
606 break;
607 case Primitive::kPrimFloat:
608 array->AsFloatArray()->SetWithoutChecks<false>(index, static_cast<float>(value));
609 break;
610 case Primitive::kPrimLong:
611 array->AsLongArray()->SetWithoutChecks<false>(index, static_cast<int64_t>(value));
612 break;
613 case Primitive::kPrimDouble:
614 array->AsDoubleArray()->SetWithoutChecks<false>(index, static_cast<double>(value));
615 break;
Sebastien Hertzee1d79a2014-02-21 15:46:30 +0100616 case Primitive::kPrimNot:
617 LOG(FATAL) << "ObjectArray should be treated as Object";
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100618 break;
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100619 default:
620 LOG(FATAL) << "Unsupported type " << array_type;
621 }
622}
623
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100624} // namespace art