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