1 /* 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 #ifndef ART_RUNTIME_TRANSACTION_H_ 18 #define ART_RUNTIME_TRANSACTION_H_ 19 20 #include "base/macros.h" 21 #include "base/mutex.h" 22 #include "object_callbacks.h" 23 #include "offsets.h" 24 #include "primitive.h" 25 #include "safe_map.h" 26 27 #include <list> 28 #include <map> 29 30 namespace art { 31 namespace mirror { 32 class Array; 33 class Object; 34 class String; 35 } 36 class InternTable; 37 38 class Transaction { 39 public: 40 Transaction(); 41 ~Transaction(); 42 43 // Record object field changes. 44 void RecordWriteField32(mirror::Object* obj, MemberOffset field_offset, uint32_t value, 45 bool is_volatile) 46 LOCKS_EXCLUDED(log_lock_); 47 void RecordWriteField64(mirror::Object* obj, MemberOffset field_offset, uint64_t value, 48 bool is_volatile) 49 LOCKS_EXCLUDED(log_lock_); 50 void RecordWriteFieldReference(mirror::Object* obj, MemberOffset field_offset, 51 mirror::Object* value, bool is_volatile) 52 LOCKS_EXCLUDED(log_lock_); 53 54 // Record array change. 55 void RecordWriteArray(mirror::Array* array, size_t index, uint64_t value) 56 LOCKS_EXCLUDED(log_lock_) 57 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); 58 59 // Record intern string table changes. 60 void RecordStrongStringInsertion(mirror::String* s) 61 EXCLUSIVE_LOCKS_REQUIRED(Locks::intern_table_lock_) 62 LOCKS_EXCLUDED(log_lock_); 63 void RecordWeakStringInsertion(mirror::String* s) 64 EXCLUSIVE_LOCKS_REQUIRED(Locks::intern_table_lock_) 65 LOCKS_EXCLUDED(log_lock_); 66 void RecordStrongStringRemoval(mirror::String* s) 67 EXCLUSIVE_LOCKS_REQUIRED(Locks::intern_table_lock_) 68 LOCKS_EXCLUDED(log_lock_); 69 void RecordWeakStringRemoval(mirror::String* s) 70 EXCLUSIVE_LOCKS_REQUIRED(Locks::intern_table_lock_) 71 LOCKS_EXCLUDED(log_lock_); 72 73 // Abort transaction by undoing all recorded changes. 74 void Abort() 75 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) 76 LOCKS_EXCLUDED(log_lock_); 77 78 void VisitRoots(RootCallback* callback, void* arg) 79 LOCKS_EXCLUDED(log_lock_) 80 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); 81 82 private: 83 class ObjectLog { 84 public: 85 void Log32BitsValue(MemberOffset offset, uint32_t value, bool is_volatile); 86 void Log64BitsValue(MemberOffset offset, uint64_t value, bool is_volatile); 87 void LogReferenceValue(MemberOffset offset, mirror::Object* obj, bool is_volatile); 88 89 void Undo(mirror::Object* obj) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); 90 void VisitRoots(RootCallback* callback, void* arg); 91 Size()92 size_t Size() const { 93 return field_values_.size(); 94 } 95 96 private: 97 enum FieldValueKind { 98 k32Bits, 99 k64Bits, 100 kReference 101 }; 102 struct FieldValue { 103 // TODO use JValue instead ? 104 uint64_t value; 105 FieldValueKind kind; 106 bool is_volatile; 107 }; 108 109 void UndoFieldWrite(mirror::Object* obj, MemberOffset field_offset, 110 const FieldValue& field_value) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); 111 112 // Maps field's offset to its value. 113 std::map<uint32_t, FieldValue> field_values_; 114 }; 115 116 class ArrayLog { 117 public: 118 void LogValue(size_t index, uint64_t value); 119 120 void Undo(mirror::Array* obj) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); 121 Size()122 size_t Size() const { 123 return array_values_.size(); 124 } 125 126 private: 127 void UndoArrayWrite(mirror::Array* array, Primitive::Type array_type, size_t index, 128 uint64_t value) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); 129 130 // Maps index to value. 131 // TODO use JValue instead ? 132 std::map<size_t, uint64_t> array_values_; 133 }; 134 135 class InternStringLog { 136 public: 137 enum StringKind { 138 kStrongString, 139 kWeakString 140 }; 141 enum StringOp { 142 kInsert, 143 kRemove 144 }; InternStringLog(mirror::String * s,StringKind kind,StringOp op)145 InternStringLog(mirror::String* s, StringKind kind, StringOp op) 146 : str_(s), string_kind_(kind), string_op_(op) { 147 DCHECK(s != nullptr); 148 } 149 150 void Undo(InternTable* intern_table) 151 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) 152 EXCLUSIVE_LOCKS_REQUIRED(Locks::intern_table_lock_); 153 void VisitRoots(RootCallback* callback, void* arg); 154 155 private: 156 mirror::String* str_; 157 StringKind string_kind_; 158 StringOp string_op_; 159 }; 160 161 void LogInternedString(InternStringLog& log) 162 EXCLUSIVE_LOCKS_REQUIRED(Locks::intern_table_lock_) 163 LOCKS_EXCLUDED(log_lock_); 164 165 void UndoObjectModifications() 166 EXCLUSIVE_LOCKS_REQUIRED(log_lock_) 167 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); 168 void UndoArrayModifications() 169 EXCLUSIVE_LOCKS_REQUIRED(log_lock_) 170 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); 171 void UndoInternStringTableModifications() 172 EXCLUSIVE_LOCKS_REQUIRED(Locks::intern_table_lock_) 173 EXCLUSIVE_LOCKS_REQUIRED(log_lock_) 174 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); 175 176 void VisitObjectLogs(RootCallback* callback, void* arg) 177 EXCLUSIVE_LOCKS_REQUIRED(log_lock_) 178 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); 179 void VisitArrayLogs(RootCallback* callback, void* arg) 180 EXCLUSIVE_LOCKS_REQUIRED(log_lock_) 181 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); 182 void VisitStringLogs(RootCallback* callback, void* arg) 183 EXCLUSIVE_LOCKS_REQUIRED(log_lock_) 184 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); 185 186 Mutex log_lock_ ACQUIRED_AFTER(Locks::intern_table_lock_); 187 std::map<mirror::Object*, ObjectLog> object_logs_ GUARDED_BY(log_lock_); 188 std::map<mirror::Array*, ArrayLog> array_logs_ GUARDED_BY(log_lock_); 189 std::list<InternStringLog> intern_string_logs_ GUARDED_BY(log_lock_); 190 191 DISALLOW_COPY_AND_ASSIGN(Transaction); 192 }; 193 194 } // namespace art 195 196 #endif // ART_RUNTIME_TRANSACTION_H_ 197