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 "base/value_object.h" 23 #include "dex_file_types.h" 24 #include "gc_root.h" 25 #include "offsets.h" 26 #include "primitive.h" 27 #include "safe_map.h" 28 29 #include <list> 30 #include <map> 31 32 namespace art { 33 namespace mirror { 34 class Array; 35 class DexCache; 36 class Object; 37 class String; 38 } // namespace mirror 39 class InternTable; 40 41 class Transaction FINAL { 42 public: 43 static constexpr const char* kAbortExceptionDescriptor = "dalvik.system.TransactionAbortError"; 44 static constexpr const char* kAbortExceptionSignature = "Ldalvik/system/TransactionAbortError;"; 45 46 Transaction(); 47 ~Transaction(); 48 49 void Abort(const std::string& abort_message) 50 REQUIRES(!log_lock_) 51 REQUIRES_SHARED(Locks::mutator_lock_); 52 void ThrowAbortError(Thread* self, const std::string* abort_message) 53 REQUIRES(!log_lock_) 54 REQUIRES_SHARED(Locks::mutator_lock_); 55 bool IsAborted() REQUIRES(!log_lock_); 56 57 // Record object field changes. 58 void RecordWriteFieldBoolean(mirror::Object* obj, 59 MemberOffset field_offset, 60 uint8_t value, 61 bool is_volatile) 62 REQUIRES(!log_lock_); 63 void RecordWriteFieldByte(mirror::Object* obj, 64 MemberOffset field_offset, 65 int8_t value, 66 bool is_volatile) 67 REQUIRES(!log_lock_); 68 void RecordWriteFieldChar(mirror::Object* obj, 69 MemberOffset field_offset, 70 uint16_t value, 71 bool is_volatile) 72 REQUIRES(!log_lock_); 73 void RecordWriteFieldShort(mirror::Object* obj, 74 MemberOffset field_offset, 75 int16_t value, 76 bool is_volatile) 77 REQUIRES(!log_lock_); 78 void RecordWriteField32(mirror::Object* obj, 79 MemberOffset field_offset, 80 uint32_t value, 81 bool is_volatile) 82 REQUIRES(!log_lock_); 83 void RecordWriteField64(mirror::Object* obj, 84 MemberOffset field_offset, 85 uint64_t value, 86 bool is_volatile) 87 REQUIRES(!log_lock_); 88 void RecordWriteFieldReference(mirror::Object* obj, 89 MemberOffset field_offset, 90 mirror::Object* value, 91 bool is_volatile) 92 REQUIRES(!log_lock_); 93 94 // Record array change. 95 void RecordWriteArray(mirror::Array* array, size_t index, uint64_t value) 96 REQUIRES(!log_lock_) 97 REQUIRES_SHARED(Locks::mutator_lock_); 98 99 // Record intern string table changes. 100 void RecordStrongStringInsertion(ObjPtr<mirror::String> s) 101 REQUIRES(Locks::intern_table_lock_) 102 REQUIRES(!log_lock_); 103 void RecordWeakStringInsertion(ObjPtr<mirror::String> s) 104 REQUIRES(Locks::intern_table_lock_) 105 REQUIRES(!log_lock_); 106 void RecordStrongStringRemoval(ObjPtr<mirror::String> s) 107 REQUIRES(Locks::intern_table_lock_) 108 REQUIRES(!log_lock_); 109 void RecordWeakStringRemoval(ObjPtr<mirror::String> s) 110 REQUIRES(Locks::intern_table_lock_) 111 REQUIRES(!log_lock_); 112 113 // Record resolve string. 114 void RecordResolveString(ObjPtr<mirror::DexCache> dex_cache, dex::StringIndex string_idx) 115 REQUIRES_SHARED(Locks::mutator_lock_) 116 REQUIRES(!log_lock_); 117 118 // Abort transaction by undoing all recorded changes. 119 void Rollback() 120 REQUIRES_SHARED(Locks::mutator_lock_) 121 REQUIRES(!log_lock_); 122 123 void VisitRoots(RootVisitor* visitor) 124 REQUIRES(!log_lock_) 125 REQUIRES_SHARED(Locks::mutator_lock_); 126 127 private: 128 class ObjectLog : public ValueObject { 129 public: 130 void LogBooleanValue(MemberOffset offset, uint8_t value, bool is_volatile); 131 void LogByteValue(MemberOffset offset, int8_t value, bool is_volatile); 132 void LogCharValue(MemberOffset offset, uint16_t value, bool is_volatile); 133 void LogShortValue(MemberOffset offset, int16_t value, bool is_volatile); 134 void Log32BitsValue(MemberOffset offset, uint32_t value, bool is_volatile); 135 void Log64BitsValue(MemberOffset offset, uint64_t value, bool is_volatile); 136 void LogReferenceValue(MemberOffset offset, mirror::Object* obj, bool is_volatile); 137 138 void Undo(mirror::Object* obj) const REQUIRES_SHARED(Locks::mutator_lock_); 139 void VisitRoots(RootVisitor* visitor) REQUIRES_SHARED(Locks::mutator_lock_); 140 Size()141 size_t Size() const { 142 return field_values_.size(); 143 } 144 145 ObjectLog() = default; 146 ObjectLog(ObjectLog&& log) = default; 147 148 private: 149 enum FieldValueKind { 150 kBoolean, 151 kByte, 152 kChar, 153 kShort, 154 k32Bits, 155 k64Bits, 156 kReference 157 }; 158 struct FieldValue : public ValueObject { 159 // TODO use JValue instead ? 160 uint64_t value; 161 FieldValueKind kind; 162 bool is_volatile; 163 FieldValueFieldValue164 FieldValue() : value(0), kind(FieldValueKind::kBoolean), is_volatile(false) {} 165 FieldValue(FieldValue&& log) = default; 166 167 private: 168 DISALLOW_COPY_AND_ASSIGN(FieldValue); 169 }; 170 171 void LogValue(FieldValueKind kind, MemberOffset offset, uint64_t value, bool is_volatile); 172 void UndoFieldWrite(mirror::Object* obj, 173 MemberOffset field_offset, 174 const FieldValue& field_value) const REQUIRES_SHARED(Locks::mutator_lock_); 175 176 // Maps field's offset to its value. 177 std::map<uint32_t, FieldValue> field_values_; 178 179 DISALLOW_COPY_AND_ASSIGN(ObjectLog); 180 }; 181 182 class ArrayLog : public ValueObject { 183 public: 184 void LogValue(size_t index, uint64_t value); 185 186 void Undo(mirror::Array* obj) const REQUIRES_SHARED(Locks::mutator_lock_); 187 Size()188 size_t Size() const { 189 return array_values_.size(); 190 } 191 192 ArrayLog() = default; 193 ArrayLog(ArrayLog&& log) = default; 194 195 private: 196 void UndoArrayWrite(mirror::Array* array, 197 Primitive::Type array_type, 198 size_t index, 199 uint64_t value) const REQUIRES_SHARED(Locks::mutator_lock_); 200 201 // Maps index to value. 202 // TODO use JValue instead ? 203 std::map<size_t, uint64_t> array_values_; 204 205 DISALLOW_COPY_AND_ASSIGN(ArrayLog); 206 }; 207 208 class InternStringLog : public ValueObject { 209 public: 210 enum StringKind { 211 kStrongString, 212 kWeakString 213 }; 214 enum StringOp { 215 kInsert, 216 kRemove 217 }; 218 InternStringLog(ObjPtr<mirror::String> s, StringKind kind, StringOp op); 219 220 void Undo(InternTable* intern_table) const 221 REQUIRES_SHARED(Locks::mutator_lock_) 222 REQUIRES(Locks::intern_table_lock_); 223 void VisitRoots(RootVisitor* visitor) REQUIRES_SHARED(Locks::mutator_lock_); 224 225 InternStringLog() = default; 226 InternStringLog(InternStringLog&& log) = default; 227 228 private: 229 mutable GcRoot<mirror::String> str_; 230 const StringKind string_kind_; 231 const StringOp string_op_; 232 233 DISALLOW_COPY_AND_ASSIGN(InternStringLog); 234 }; 235 236 class ResolveStringLog : public ValueObject { 237 public: 238 ResolveStringLog(ObjPtr<mirror::DexCache> dex_cache, dex::StringIndex string_idx); 239 240 void Undo() const REQUIRES_SHARED(Locks::mutator_lock_); 241 242 void VisitRoots(RootVisitor* visitor) REQUIRES_SHARED(Locks::mutator_lock_); 243 244 private: 245 GcRoot<mirror::DexCache> dex_cache_; 246 const dex::StringIndex string_idx_; 247 248 DISALLOW_COPY_AND_ASSIGN(ResolveStringLog); 249 }; 250 251 void LogInternedString(InternStringLog&& log) 252 REQUIRES(Locks::intern_table_lock_) 253 REQUIRES(!log_lock_); 254 255 void UndoObjectModifications() 256 REQUIRES(log_lock_) 257 REQUIRES_SHARED(Locks::mutator_lock_); 258 void UndoArrayModifications() 259 REQUIRES(log_lock_) 260 REQUIRES_SHARED(Locks::mutator_lock_); 261 void UndoInternStringTableModifications() 262 REQUIRES(Locks::intern_table_lock_) 263 REQUIRES(log_lock_) 264 REQUIRES_SHARED(Locks::mutator_lock_); 265 void UndoResolveStringModifications() 266 REQUIRES(log_lock_) 267 REQUIRES_SHARED(Locks::mutator_lock_); 268 269 void VisitObjectLogs(RootVisitor* visitor) 270 REQUIRES(log_lock_) 271 REQUIRES_SHARED(Locks::mutator_lock_); 272 void VisitArrayLogs(RootVisitor* visitor) 273 REQUIRES(log_lock_) 274 REQUIRES_SHARED(Locks::mutator_lock_); 275 void VisitInternStringLogs(RootVisitor* visitor) 276 REQUIRES(log_lock_) 277 REQUIRES_SHARED(Locks::mutator_lock_); 278 void VisitResolveStringLogs(RootVisitor* visitor) 279 REQUIRES(log_lock_) 280 REQUIRES_SHARED(Locks::mutator_lock_); 281 282 const std::string& GetAbortMessage() REQUIRES(!log_lock_); 283 284 Mutex log_lock_ ACQUIRED_AFTER(Locks::intern_table_lock_); 285 std::map<mirror::Object*, ObjectLog> object_logs_ GUARDED_BY(log_lock_); 286 std::map<mirror::Array*, ArrayLog> array_logs_ GUARDED_BY(log_lock_); 287 std::list<InternStringLog> intern_string_logs_ GUARDED_BY(log_lock_); 288 std::list<ResolveStringLog> resolve_string_logs_ GUARDED_BY(log_lock_); 289 bool aborted_ GUARDED_BY(log_lock_); 290 std::string abort_message_ GUARDED_BY(log_lock_); 291 292 DISALLOW_COPY_AND_ASSIGN(Transaction); 293 }; 294 295 } // namespace art 296 297 #endif // ART_RUNTIME_TRANSACTION_H_ 298