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 "gc_root.h" 24 #include "object_callbacks.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 Object; 36 class String; 37 } 38 class InternTable; 39 40 class Transaction FINAL { 41 public: 42 static constexpr const char* kAbortExceptionDescriptor = "dalvik.system.TransactionAbortError"; 43 static constexpr const char* kAbortExceptionSignature = "Ldalvik/system/TransactionAbortError;"; 44 45 Transaction(); 46 ~Transaction(); 47 48 void Abort(const std::string& abort_message) 49 REQUIRES(!log_lock_) 50 SHARED_REQUIRES(Locks::mutator_lock_); 51 void ThrowAbortError(Thread* self, const std::string* abort_message) 52 REQUIRES(!log_lock_) 53 SHARED_REQUIRES(Locks::mutator_lock_); 54 bool IsAborted() REQUIRES(!log_lock_); 55 56 // Record object field changes. 57 void RecordWriteFieldBoolean(mirror::Object* obj, MemberOffset field_offset, uint8_t value, 58 bool is_volatile) 59 REQUIRES(!log_lock_); 60 void RecordWriteFieldByte(mirror::Object* obj, MemberOffset field_offset, int8_t value, 61 bool is_volatile) 62 REQUIRES(!log_lock_); 63 void RecordWriteFieldChar(mirror::Object* obj, MemberOffset field_offset, uint16_t value, 64 bool is_volatile) 65 REQUIRES(!log_lock_); 66 void RecordWriteFieldShort(mirror::Object* obj, MemberOffset field_offset, int16_t value, 67 bool is_volatile) 68 REQUIRES(!log_lock_); 69 void RecordWriteField32(mirror::Object* obj, MemberOffset field_offset, uint32_t value, 70 bool is_volatile) 71 REQUIRES(!log_lock_); 72 void RecordWriteField64(mirror::Object* obj, MemberOffset field_offset, uint64_t value, 73 bool is_volatile) 74 REQUIRES(!log_lock_); 75 void RecordWriteFieldReference(mirror::Object* obj, MemberOffset field_offset, 76 mirror::Object* value, bool is_volatile) 77 REQUIRES(!log_lock_); 78 79 // Record array change. 80 void RecordWriteArray(mirror::Array* array, size_t index, uint64_t value) 81 REQUIRES(!log_lock_) 82 SHARED_REQUIRES(Locks::mutator_lock_); 83 84 // Record intern string table changes. 85 void RecordStrongStringInsertion(mirror::String* s) 86 REQUIRES(Locks::intern_table_lock_) 87 REQUIRES(!log_lock_); 88 void RecordWeakStringInsertion(mirror::String* s) 89 REQUIRES(Locks::intern_table_lock_) 90 REQUIRES(!log_lock_); 91 void RecordStrongStringRemoval(mirror::String* s) 92 REQUIRES(Locks::intern_table_lock_) 93 REQUIRES(!log_lock_); 94 void RecordWeakStringRemoval(mirror::String* s) 95 REQUIRES(Locks::intern_table_lock_) 96 REQUIRES(!log_lock_); 97 98 // Abort transaction by undoing all recorded changes. 99 void Rollback() 100 SHARED_REQUIRES(Locks::mutator_lock_) 101 REQUIRES(!log_lock_); 102 103 void VisitRoots(RootVisitor* visitor) 104 REQUIRES(!log_lock_) 105 SHARED_REQUIRES(Locks::mutator_lock_); 106 107 private: 108 class ObjectLog : public ValueObject { 109 public: 110 void LogBooleanValue(MemberOffset offset, uint8_t value, bool is_volatile); 111 void LogByteValue(MemberOffset offset, int8_t value, bool is_volatile); 112 void LogCharValue(MemberOffset offset, uint16_t value, bool is_volatile); 113 void LogShortValue(MemberOffset offset, int16_t value, bool is_volatile); 114 void Log32BitsValue(MemberOffset offset, uint32_t value, bool is_volatile); 115 void Log64BitsValue(MemberOffset offset, uint64_t value, bool is_volatile); 116 void LogReferenceValue(MemberOffset offset, mirror::Object* obj, bool is_volatile); 117 118 void Undo(mirror::Object* obj) SHARED_REQUIRES(Locks::mutator_lock_); 119 void VisitRoots(RootVisitor* visitor) SHARED_REQUIRES(Locks::mutator_lock_); 120 Size()121 size_t Size() const { 122 return field_values_.size(); 123 } 124 125 private: 126 enum FieldValueKind { 127 kBoolean, 128 kByte, 129 kChar, 130 kShort, 131 k32Bits, 132 k64Bits, 133 kReference 134 }; 135 struct FieldValue : public ValueObject { 136 // TODO use JValue instead ? 137 uint64_t value; 138 FieldValueKind kind; 139 bool is_volatile; 140 }; 141 142 void LogValue(FieldValueKind kind, MemberOffset offset, uint64_t value, bool is_volatile); 143 void UndoFieldWrite(mirror::Object* obj, MemberOffset field_offset, 144 const FieldValue& field_value) SHARED_REQUIRES(Locks::mutator_lock_); 145 146 // Maps field's offset to its value. 147 std::map<uint32_t, FieldValue> field_values_; 148 }; 149 150 class ArrayLog : public ValueObject { 151 public: 152 void LogValue(size_t index, uint64_t value); 153 154 void Undo(mirror::Array* obj) SHARED_REQUIRES(Locks::mutator_lock_); 155 Size()156 size_t Size() const { 157 return array_values_.size(); 158 } 159 160 private: 161 void UndoArrayWrite(mirror::Array* array, Primitive::Type array_type, size_t index, 162 uint64_t value) SHARED_REQUIRES(Locks::mutator_lock_); 163 164 // Maps index to value. 165 // TODO use JValue instead ? 166 std::map<size_t, uint64_t> array_values_; 167 }; 168 169 class InternStringLog : public ValueObject { 170 public: 171 enum StringKind { 172 kStrongString, 173 kWeakString 174 }; 175 enum StringOp { 176 kInsert, 177 kRemove 178 }; InternStringLog(mirror::String * s,StringKind kind,StringOp op)179 InternStringLog(mirror::String* s, StringKind kind, StringOp op) 180 : str_(s), string_kind_(kind), string_op_(op) { 181 DCHECK(s != nullptr); 182 } 183 184 void Undo(InternTable* intern_table) 185 SHARED_REQUIRES(Locks::mutator_lock_) 186 REQUIRES(Locks::intern_table_lock_); 187 void VisitRoots(RootVisitor* visitor) SHARED_REQUIRES(Locks::mutator_lock_); 188 189 private: 190 mirror::String* str_; 191 const StringKind string_kind_; 192 const StringOp string_op_; 193 }; 194 195 void LogInternedString(const InternStringLog& log) 196 REQUIRES(Locks::intern_table_lock_) 197 REQUIRES(!log_lock_); 198 199 void UndoObjectModifications() 200 REQUIRES(log_lock_) 201 SHARED_REQUIRES(Locks::mutator_lock_); 202 void UndoArrayModifications() 203 REQUIRES(log_lock_) 204 SHARED_REQUIRES(Locks::mutator_lock_); 205 void UndoInternStringTableModifications() 206 REQUIRES(Locks::intern_table_lock_) 207 REQUIRES(log_lock_) 208 SHARED_REQUIRES(Locks::mutator_lock_); 209 210 void VisitObjectLogs(RootVisitor* visitor) 211 REQUIRES(log_lock_) 212 SHARED_REQUIRES(Locks::mutator_lock_); 213 void VisitArrayLogs(RootVisitor* visitor) 214 REQUIRES(log_lock_) 215 SHARED_REQUIRES(Locks::mutator_lock_); 216 void VisitStringLogs(RootVisitor* visitor) 217 REQUIRES(log_lock_) 218 SHARED_REQUIRES(Locks::mutator_lock_); 219 220 const std::string& GetAbortMessage() REQUIRES(!log_lock_); 221 222 Mutex log_lock_ ACQUIRED_AFTER(Locks::intern_table_lock_); 223 std::map<mirror::Object*, ObjectLog> object_logs_ GUARDED_BY(log_lock_); 224 std::map<mirror::Array*, ArrayLog> array_logs_ GUARDED_BY(log_lock_); 225 std::list<InternStringLog> intern_string_logs_ GUARDED_BY(log_lock_); 226 bool aborted_ GUARDED_BY(log_lock_); 227 std::string abort_message_ GUARDED_BY(log_lock_); 228 229 DISALLOW_COPY_AND_ASSIGN(Transaction); 230 }; 231 232 } // namespace art 233 234 #endif // ART_RUNTIME_TRANSACTION_H_ 235