1d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz/* 2d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz * Copyright (C) 2014 The Android Open Source Project 3d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz * 4d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz * Licensed under the Apache License, Version 2.0 (the "License"); 5d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz * you may not use this file except in compliance with the License. 6d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz * You may obtain a copy of the License at 7d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz * 8d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz * http://www.apache.org/licenses/LICENSE-2.0 9d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz * 10d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz * Unless required by applicable law or agreed to in writing, software 11d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz * distributed under the License is distributed on an "AS IS" BASIS, 12d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz * See the License for the specific language governing permissions and 14d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz * limitations under the License. 15d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz */ 16d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz 17d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz#include "transaction.h" 18d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz 19d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz#include "base/stl_util.h" 20d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz#include "base/logging.h" 21d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz#include "gc/accounting/card_table-inl.h" 22d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz#include "intern_table.h" 23d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz#include "mirror/object-inl.h" 24d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz#include "mirror/object_array-inl.h" 25d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz 26d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz#include <list> 27d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz 28d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertznamespace art { 29d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz 30d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz// TODO: remove (only used for debugging purpose). 31d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertzstatic constexpr bool kEnableTransactionStats = false; 32d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz 33d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien HertzTransaction::Transaction() : log_lock_("transaction log lock", kTransactionLogLock) { 34d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz CHECK(Runtime::Current()->IsCompiler()); 35d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz} 36d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz 37d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien HertzTransaction::~Transaction() { 38d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz if (kEnableTransactionStats) { 39d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz MutexLock mu(Thread::Current(), log_lock_); 40d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz size_t objects_count = object_logs_.size(); 41d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz size_t field_values_count = 0; 42d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz for (auto it : object_logs_) { 43d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz field_values_count += it.second.Size(); 44d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz } 45d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz size_t array_count = array_logs_.size(); 46d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz size_t array_values_count = 0; 47d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz for (auto it : array_logs_) { 48d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz array_values_count += it.second.Size(); 49d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz } 50d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz size_t string_count = intern_string_logs_.size(); 51d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz LOG(INFO) << "Transaction::~Transaction" 52d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz << ": objects_count=" << objects_count 53d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz << ", field_values_count=" << field_values_count 54d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz << ", array_count=" << array_count 55d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz << ", array_values_count=" << array_values_count 56d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz << ", string_count=" << string_count; 57d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz } 58d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz} 59d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz 60d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertzvoid Transaction::RecordWriteField32(mirror::Object* obj, MemberOffset field_offset, uint32_t value, 61d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz bool is_volatile) { 62d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz DCHECK(obj != nullptr); 63d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz MutexLock mu(Thread::Current(), log_lock_); 64d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz ObjectLog& object_log = object_logs_[obj]; 65d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz object_log.Log32BitsValue(field_offset, value, is_volatile); 66d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz} 67d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz 68d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertzvoid Transaction::RecordWriteField64(mirror::Object* obj, MemberOffset field_offset, uint64_t value, 69d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz bool is_volatile) { 70d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz DCHECK(obj != nullptr); 71d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz MutexLock mu(Thread::Current(), log_lock_); 72d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz ObjectLog& object_log = object_logs_[obj]; 73d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz object_log.Log64BitsValue(field_offset, value, is_volatile); 74d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz} 75d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz 76d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertzvoid Transaction::RecordWriteFieldReference(mirror::Object* obj, MemberOffset field_offset, 77d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz mirror::Object* value, bool is_volatile) { 78d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz DCHECK(obj != nullptr); 79d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz MutexLock mu(Thread::Current(), log_lock_); 80d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz ObjectLog& object_log = object_logs_[obj]; 81d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz object_log.LogReferenceValue(field_offset, value, is_volatile); 82d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz} 83d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz 84d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertzvoid Transaction::RecordWriteArray(mirror::Array* array, size_t index, uint64_t value) { 85d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz DCHECK(array != nullptr); 86d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz DCHECK(array->IsArrayInstance()); 87ee1d79a603c77c0667b27c075a983579d5c51f7eSebastien Hertz DCHECK(!array->IsObjectArray()); 88d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz MutexLock mu(Thread::Current(), log_lock_); 89d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz ArrayLog& array_log = array_logs_[array]; 90d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz array_log.LogValue(index, value); 91d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz} 92d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz 93d910fcef539e12ab181e56ec80684f39c4e95733Mathieu Chartiervoid Transaction::RecordStrongStringInsertion(mirror::String* s) { 94d910fcef539e12ab181e56ec80684f39c4e95733Mathieu Chartier InternStringLog log(s, InternStringLog::kStrongString, InternStringLog::kInsert); 95d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz LogInternedString(log); 96d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz} 97d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz 98d910fcef539e12ab181e56ec80684f39c4e95733Mathieu Chartiervoid Transaction::RecordWeakStringInsertion(mirror::String* s) { 99d910fcef539e12ab181e56ec80684f39c4e95733Mathieu Chartier InternStringLog log(s, InternStringLog::kWeakString, InternStringLog::kInsert); 100d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz LogInternedString(log); 101d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz} 102d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz 103d910fcef539e12ab181e56ec80684f39c4e95733Mathieu Chartiervoid Transaction::RecordStrongStringRemoval(mirror::String* s) { 104d910fcef539e12ab181e56ec80684f39c4e95733Mathieu Chartier InternStringLog log(s, InternStringLog::kStrongString, InternStringLog::kRemove); 105d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz LogInternedString(log); 106d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz} 107d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz 108d910fcef539e12ab181e56ec80684f39c4e95733Mathieu Chartiervoid Transaction::RecordWeakStringRemoval(mirror::String* s) { 109d910fcef539e12ab181e56ec80684f39c4e95733Mathieu Chartier InternStringLog log(s, InternStringLog::kWeakString, InternStringLog::kRemove); 110d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz LogInternedString(log); 111d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz} 112d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz 113d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertzvoid Transaction::LogInternedString(InternStringLog& log) { 114d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz Locks::intern_table_lock_->AssertExclusiveHeld(Thread::Current()); 115d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz MutexLock mu(Thread::Current(), log_lock_); 116d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz intern_string_logs_.push_front(log); 117d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz} 118d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz 119d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertzvoid Transaction::Abort() { 120d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz CHECK(!Runtime::Current()->IsActiveTransaction()); 121d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz Thread* self = Thread::Current(); 122d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz self->AssertNoPendingException(); 123d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz MutexLock mu1(self, *Locks::intern_table_lock_); 124d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz MutexLock mu2(self, log_lock_); 125d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz UndoObjectModifications(); 126d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz UndoArrayModifications(); 127d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz UndoInternStringTableModifications(); 128d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz} 129d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz 130d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertzvoid Transaction::UndoObjectModifications() { 131d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz // TODO we may not need to restore objects allocated during this transaction. Or we could directly 132d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz // remove them from the heap. 133d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz for (auto it : object_logs_) { 134d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz it.second.Undo(it.first); 135d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz } 136d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz object_logs_.clear(); 137d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz} 138d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz 139d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertzvoid Transaction::UndoArrayModifications() { 140d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz // TODO we may not need to restore array allocated during this transaction. Or we could directly 141d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz // remove them from the heap. 142d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz for (auto it : array_logs_) { 143d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz it.second.Undo(it.first); 144d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz } 145d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz array_logs_.clear(); 146d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz} 147d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz 148d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertzvoid Transaction::UndoInternStringTableModifications() { 149d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz InternTable* const intern_table = Runtime::Current()->GetInternTable(); 150d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz // We want to undo each operation from the most recent to the oldest. List has been filled so the 151d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz // most recent operation is at list begin so just have to iterate over it. 152d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz for (InternStringLog& string_log : intern_string_logs_) { 153d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz string_log.Undo(intern_table); 154d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz } 155d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz intern_string_logs_.clear(); 156d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz} 157d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz 158d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertzvoid Transaction::VisitRoots(RootCallback* callback, void* arg) { 159d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz MutexLock mu(Thread::Current(), log_lock_); 160d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz VisitObjectLogs(callback, arg); 161d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz VisitArrayLogs(callback, arg); 162d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz VisitStringLogs(callback, arg); 163d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz} 164d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz 165d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertzvoid Transaction::VisitObjectLogs(RootCallback* callback, void* arg) { 166d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz // List of moving roots. 167d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz typedef std::pair<mirror::Object*, mirror::Object*> ObjectPair; 168d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz std::list<ObjectPair> moving_roots; 169d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz 170d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz // Visit roots. 171d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz for (auto it : object_logs_) { 172d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz it.second.VisitRoots(callback, arg); 173d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz mirror::Object* old_root = it.first; 174815873ecc312b1d231acce71e1a16f42cdaf09f2Mathieu Chartier mirror::Object* new_root = old_root; 17512f7423a2bb4bfab76700d84eb6d4338d211983aMathieu Chartier callback(&new_root, arg, RootInfo(kRootUnknown)); 176d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz if (new_root != old_root) { 177d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz moving_roots.push_back(std::make_pair(old_root, new_root)); 178d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz } 179d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz } 180d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz 181d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz // Update object logs with moving roots. 182d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz for (const ObjectPair& pair : moving_roots) { 183d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz mirror::Object* old_root = pair.first; 184d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz mirror::Object* new_root = pair.second; 185d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz auto old_root_it = object_logs_.find(old_root); 186d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz CHECK(old_root_it != object_logs_.end()); 187d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz CHECK(object_logs_.find(new_root) == object_logs_.end()); 188d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz object_logs_.insert(std::make_pair(new_root, old_root_it->second)); 189d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz object_logs_.erase(old_root_it); 190d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz } 191d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz} 192d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz 193d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertzvoid Transaction::VisitArrayLogs(RootCallback* callback, void* arg) { 194d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz // List of moving roots. 195d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz typedef std::pair<mirror::Array*, mirror::Array*> ArrayPair; 196d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz std::list<ArrayPair> moving_roots; 197d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz 198d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz for (auto it : array_logs_) { 199d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz mirror::Array* old_root = it.first; 200ee1d79a603c77c0667b27c075a983579d5c51f7eSebastien Hertz CHECK(!old_root->IsObjectArray()); 201815873ecc312b1d231acce71e1a16f42cdaf09f2Mathieu Chartier mirror::Array* new_root = old_root; 20212f7423a2bb4bfab76700d84eb6d4338d211983aMathieu Chartier callback(reinterpret_cast<mirror::Object**>(&new_root), arg, RootInfo(kRootUnknown)); 203d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz if (new_root != old_root) { 204d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz moving_roots.push_back(std::make_pair(old_root, new_root)); 205d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz } 206d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz } 207d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz 208d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz // Update array logs with moving roots. 209d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz for (const ArrayPair& pair : moving_roots) { 210d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz mirror::Array* old_root = pair.first; 211d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz mirror::Array* new_root = pair.second; 212d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz auto old_root_it = array_logs_.find(old_root); 213d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz CHECK(old_root_it != array_logs_.end()); 214d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz CHECK(array_logs_.find(new_root) == array_logs_.end()); 215d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz array_logs_.insert(std::make_pair(new_root, old_root_it->second)); 216d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz array_logs_.erase(old_root_it); 217d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz } 218d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz} 219d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz 220d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertzvoid Transaction::VisitStringLogs(RootCallback* callback, void* arg) { 221d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz for (InternStringLog& log : intern_string_logs_) { 222d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz log.VisitRoots(callback, arg); 223d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz } 224d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz} 225d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz 226d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertzvoid Transaction::ObjectLog::Log32BitsValue(MemberOffset offset, uint32_t value, bool is_volatile) { 227d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz auto it = field_values_.find(offset.Uint32Value()); 228d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz if (it == field_values_.end()) { 229d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz ObjectLog::FieldValue field_value; 230d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz field_value.value = value; 231d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz field_value.is_volatile = is_volatile; 232d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz field_value.kind = ObjectLog::k32Bits; 233d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz field_values_.insert(std::make_pair(offset.Uint32Value(), field_value)); 234d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz } 235d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz} 236d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz 237d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertzvoid Transaction::ObjectLog::Log64BitsValue(MemberOffset offset, uint64_t value, bool is_volatile) { 238d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz auto it = field_values_.find(offset.Uint32Value()); 239d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz if (it == field_values_.end()) { 240d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz ObjectLog::FieldValue field_value; 241d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz field_value.value = value; 242d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz field_value.is_volatile = is_volatile; 243d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz field_value.kind = ObjectLog::k64Bits; 244d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz field_values_.insert(std::make_pair(offset.Uint32Value(), field_value)); 245d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz } 246d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz} 247d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz 248d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertzvoid Transaction::ObjectLog::LogReferenceValue(MemberOffset offset, mirror::Object* obj, bool is_volatile) { 249d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz auto it = field_values_.find(offset.Uint32Value()); 250d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz if (it == field_values_.end()) { 251d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz ObjectLog::FieldValue field_value; 252d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz field_value.value = reinterpret_cast<uintptr_t>(obj); 253d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz field_value.is_volatile = is_volatile; 254d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz field_value.kind = ObjectLog::kReference; 255d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz field_values_.insert(std::make_pair(offset.Uint32Value(), field_value)); 256d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz } 257d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz} 258d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz 259d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertzvoid Transaction::ObjectLog::Undo(mirror::Object* obj) { 260d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz for (auto& it : field_values_) { 261d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz // Garbage collector needs to access object's class and array's length. So we don't rollback 262d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz // these values. 263d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz MemberOffset field_offset(it.first); 264d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz if (field_offset.Uint32Value() == mirror::Class::ClassOffset().Uint32Value()) { 265d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz // Skip Object::class field. 266d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz continue; 267d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz } 268d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz if (obj->IsArrayInstance() && 269d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz field_offset.Uint32Value() == mirror::Array::LengthOffset().Uint32Value()) { 270d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz // Skip Array::length field. 271d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz continue; 272d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz } 273d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz FieldValue& field_value = it.second; 274d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz UndoFieldWrite(obj, field_offset, field_value); 275d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz } 276d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz} 277d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz 278d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertzvoid Transaction::ObjectLog::UndoFieldWrite(mirror::Object* obj, MemberOffset field_offset, 279d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz const FieldValue& field_value) { 280d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz // TODO We may want to abort a transaction while still being in transaction mode. In this case, 281d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz // we'd need to disable the check. 282d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz constexpr bool kCheckTransaction = true; 283d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz switch (field_value.kind) { 284d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz case k32Bits: 285b0fa5dc7769c1e054032f39de0a3f6d6dd06f8cfIan Rogers if (UNLIKELY(field_value.is_volatile)) { 286b0fa5dc7769c1e054032f39de0a3f6d6dd06f8cfIan Rogers obj->SetField32Volatile<false, kCheckTransaction>(field_offset, 287b0fa5dc7769c1e054032f39de0a3f6d6dd06f8cfIan Rogers static_cast<uint32_t>(field_value.value)); 288b0fa5dc7769c1e054032f39de0a3f6d6dd06f8cfIan Rogers } else { 289b0fa5dc7769c1e054032f39de0a3f6d6dd06f8cfIan Rogers obj->SetField32<false, kCheckTransaction>(field_offset, 290b0fa5dc7769c1e054032f39de0a3f6d6dd06f8cfIan Rogers static_cast<uint32_t>(field_value.value)); 291b0fa5dc7769c1e054032f39de0a3f6d6dd06f8cfIan Rogers } 292d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz break; 293d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz case k64Bits: 294b0fa5dc7769c1e054032f39de0a3f6d6dd06f8cfIan Rogers if (UNLIKELY(field_value.is_volatile)) { 295b0fa5dc7769c1e054032f39de0a3f6d6dd06f8cfIan Rogers obj->SetField64Volatile<false, kCheckTransaction>(field_offset, field_value.value); 296b0fa5dc7769c1e054032f39de0a3f6d6dd06f8cfIan Rogers } else { 297b0fa5dc7769c1e054032f39de0a3f6d6dd06f8cfIan Rogers obj->SetField64<false, kCheckTransaction>(field_offset, field_value.value); 298b0fa5dc7769c1e054032f39de0a3f6d6dd06f8cfIan Rogers } 299d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz break; 300d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz case kReference: 301b0fa5dc7769c1e054032f39de0a3f6d6dd06f8cfIan Rogers if (UNLIKELY(field_value.is_volatile)) { 302b0fa5dc7769c1e054032f39de0a3f6d6dd06f8cfIan Rogers obj->SetFieldObjectVolatile<false, kCheckTransaction>(field_offset, 303b0fa5dc7769c1e054032f39de0a3f6d6dd06f8cfIan Rogers reinterpret_cast<mirror::Object*>(field_value.value)); 304b0fa5dc7769c1e054032f39de0a3f6d6dd06f8cfIan Rogers } else { 305b0fa5dc7769c1e054032f39de0a3f6d6dd06f8cfIan Rogers obj->SetFieldObject<false, kCheckTransaction>(field_offset, 306b0fa5dc7769c1e054032f39de0a3f6d6dd06f8cfIan Rogers reinterpret_cast<mirror::Object*>(field_value.value)); 307b0fa5dc7769c1e054032f39de0a3f6d6dd06f8cfIan Rogers } 308d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz break; 309d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz default: 310d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz LOG(FATAL) << "Unknown value kind " << field_value.kind; 311d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz break; 312d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz } 313d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz} 314d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz 315d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertzvoid Transaction::ObjectLog::VisitRoots(RootCallback* callback, void* arg) { 316d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz for (auto it : field_values_) { 317d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz FieldValue& field_value = it.second; 318d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz if (field_value.kind == ObjectLog::kReference) { 319815873ecc312b1d231acce71e1a16f42cdaf09f2Mathieu Chartier mirror::Object* obj = 320815873ecc312b1d231acce71e1a16f42cdaf09f2Mathieu Chartier reinterpret_cast<mirror::Object*>(static_cast<uintptr_t>(field_value.value)); 321a559ccb7aa56a5871b1e77857c2b5e7101b8d371Sebastien Hertz if (obj != nullptr) { 32212f7423a2bb4bfab76700d84eb6d4338d211983aMathieu Chartier callback(&obj, arg, RootInfo(kRootUnknown)); 323a559ccb7aa56a5871b1e77857c2b5e7101b8d371Sebastien Hertz field_value.value = reinterpret_cast<uintptr_t>(obj); 324a559ccb7aa56a5871b1e77857c2b5e7101b8d371Sebastien Hertz } 325d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz } 326d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz } 327d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz} 328d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz 329d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertzvoid Transaction::InternStringLog::Undo(InternTable* intern_table) { 330d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz DCHECK(intern_table != nullptr); 331d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz switch (string_op_) { 332d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz case InternStringLog::kInsert: { 333d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz switch (string_kind_) { 334d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz case InternStringLog::kStrongString: 335d910fcef539e12ab181e56ec80684f39c4e95733Mathieu Chartier intern_table->RemoveStrongFromTransaction(str_); 336d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz break; 337d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz case InternStringLog::kWeakString: 338d910fcef539e12ab181e56ec80684f39c4e95733Mathieu Chartier intern_table->RemoveWeakFromTransaction(str_); 339d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz break; 340d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz default: 341d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz LOG(FATAL) << "Unknown interned string kind"; 342d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz break; 343d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz } 344d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz break; 345d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz } 346d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz case InternStringLog::kRemove: { 347d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz switch (string_kind_) { 348d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz case InternStringLog::kStrongString: 349d910fcef539e12ab181e56ec80684f39c4e95733Mathieu Chartier intern_table->InsertStrongFromTransaction(str_); 350d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz break; 351d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz case InternStringLog::kWeakString: 352d910fcef539e12ab181e56ec80684f39c4e95733Mathieu Chartier intern_table->InsertWeakFromTransaction(str_); 353d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz break; 354d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz default: 355d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz LOG(FATAL) << "Unknown interned string kind"; 356d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz break; 357d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz } 358d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz break; 359d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz } 360d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz default: 361d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz LOG(FATAL) << "Unknown interned string op"; 362d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz break; 363d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz } 364d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz} 365d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz 366d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertzvoid Transaction::InternStringLog::VisitRoots(RootCallback* callback, void* arg) { 36712f7423a2bb4bfab76700d84eb6d4338d211983aMathieu Chartier callback(reinterpret_cast<mirror::Object**>(&str_), arg, RootInfo(kRootInternedString)); 368d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz} 369d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz 370d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertzvoid Transaction::ArrayLog::LogValue(size_t index, uint64_t value) { 371d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz auto it = array_values_.find(index); 372d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz if (it == array_values_.end()) { 373d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz array_values_.insert(std::make_pair(index, value)); 374d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz } 375d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz} 376d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz 377d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertzvoid Transaction::ArrayLog::Undo(mirror::Array* array) { 378d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz DCHECK(array != nullptr); 379d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz DCHECK(array->IsArrayInstance()); 380d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz Primitive::Type type = array->GetClass()->GetComponentType()->GetPrimitiveType(); 381d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz for (auto it : array_values_) { 382d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz UndoArrayWrite(array, type, it.first, it.second); 383d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz } 384d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz} 385d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz 386d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertzvoid Transaction::ArrayLog::UndoArrayWrite(mirror::Array* array, Primitive::Type array_type, 387d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz size_t index, uint64_t value) { 388d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz // TODO We may want to abort a transaction while still being in transaction mode. In this case, 389d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz // we'd need to disable the check. 390d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz switch (array_type) { 391d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz case Primitive::kPrimBoolean: 392d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz array->AsBooleanArray()->SetWithoutChecks<false>(index, static_cast<uint8_t>(value)); 393d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz break; 394d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz case Primitive::kPrimByte: 395d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz array->AsByteArray()->SetWithoutChecks<false>(index, static_cast<int8_t>(value)); 396d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz break; 397d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz case Primitive::kPrimChar: 398d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz array->AsCharArray()->SetWithoutChecks<false>(index, static_cast<uint16_t>(value)); 399d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz break; 400d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz case Primitive::kPrimShort: 401d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz array->AsShortArray()->SetWithoutChecks<false>(index, static_cast<int16_t>(value)); 402d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz break; 403d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz case Primitive::kPrimInt: 404d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz array->AsIntArray()->SetWithoutChecks<false>(index, static_cast<int32_t>(value)); 405d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz break; 406d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz case Primitive::kPrimFloat: 407d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz array->AsFloatArray()->SetWithoutChecks<false>(index, static_cast<float>(value)); 408d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz break; 409d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz case Primitive::kPrimLong: 410d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz array->AsLongArray()->SetWithoutChecks<false>(index, static_cast<int64_t>(value)); 411d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz break; 412d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz case Primitive::kPrimDouble: 413d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz array->AsDoubleArray()->SetWithoutChecks<false>(index, static_cast<double>(value)); 414d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz break; 415ee1d79a603c77c0667b27c075a983579d5c51f7eSebastien Hertz case Primitive::kPrimNot: 416ee1d79a603c77c0667b27c075a983579d5c51f7eSebastien Hertz LOG(FATAL) << "ObjectArray should be treated as Object"; 417d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz break; 418d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz default: 419d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz LOG(FATAL) << "Unsupported type " << array_type; 420d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz } 421d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz} 422d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz 423d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz} // namespace art 424