blob: 747c2d0f38c343914363d95a5674f0d61c023df5 [file] [log] [blame]
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +01001/*
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"
Ian Rogers6a3c1fc2014-10-31 00:33:20 -070022#include "base/value_object.h"
Andreas Gampe8a0128a2016-11-28 07:38:35 -080023#include "dex_file_types.h"
Mathieu Chartiere34fa1d2015-01-14 14:55:47 -080024#include "gc_root.h"
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +010025#include "offsets.h"
26#include "primitive.h"
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +010027#include "safe_map.h"
28
29#include <list>
30#include <map>
31
32namespace art {
33namespace mirror {
34class Array;
Mathieu Chartierbb816d62016-09-07 10:17:46 -070035class DexCache;
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +010036class Object;
37class String;
Andreas Gampedeae7db2017-05-30 09:56:41 -070038} // namespace mirror
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +010039class InternTable;
40
Ian Rogers6a3c1fc2014-10-31 00:33:20 -070041class Transaction FINAL {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +010042 public:
Sebastien Hertz2fd7e692015-04-02 11:11:19 +020043 static constexpr const char* kAbortExceptionDescriptor = "dalvik.system.TransactionAbortError";
44 static constexpr const char* kAbortExceptionSignature = "Ldalvik/system/TransactionAbortError;";
45
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +010046 Transaction();
47 ~Transaction();
48
Sebastien Hertz1c80bec2015-02-03 11:58:06 +010049 void Abort(const std::string& abort_message)
Mathieu Chartier90443472015-07-16 20:32:27 -070050 REQUIRES(!log_lock_)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -070051 REQUIRES_SHARED(Locks::mutator_lock_);
Sebastien Hertzb81e1cd2015-04-28 12:31:41 +020052 void ThrowAbortError(Thread* self, const std::string* abort_message)
Mathieu Chartier90443472015-07-16 20:32:27 -070053 REQUIRES(!log_lock_)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -070054 REQUIRES_SHARED(Locks::mutator_lock_);
Mathieu Chartier90443472015-07-16 20:32:27 -070055 bool IsAborted() REQUIRES(!log_lock_);
Sebastien Hertz1c80bec2015-02-03 11:58:06 +010056
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +010057 // Record object field changes.
Mathieu Chartier38e954c2017-02-03 16:06:35 -080058 void RecordWriteFieldBoolean(mirror::Object* obj,
59 MemberOffset field_offset,
60 uint8_t value,
Fred Shih37f05ef2014-07-16 18:38:08 -070061 bool is_volatile)
Mathieu Chartier90443472015-07-16 20:32:27 -070062 REQUIRES(!log_lock_);
Mathieu Chartier38e954c2017-02-03 16:06:35 -080063 void RecordWriteFieldByte(mirror::Object* obj,
64 MemberOffset field_offset,
65 int8_t value,
Fred Shih37f05ef2014-07-16 18:38:08 -070066 bool is_volatile)
Mathieu Chartier90443472015-07-16 20:32:27 -070067 REQUIRES(!log_lock_);
Mathieu Chartier38e954c2017-02-03 16:06:35 -080068 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,
Fred Shih37f05ef2014-07-16 18:38:08 -070076 bool is_volatile)
Mathieu Chartier90443472015-07-16 20:32:27 -070077 REQUIRES(!log_lock_);
Mathieu Chartier38e954c2017-02-03 16:06:35 -080078 void RecordWriteField32(mirror::Object* obj,
79 MemberOffset field_offset,
80 uint32_t value,
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +010081 bool is_volatile)
Mathieu Chartier90443472015-07-16 20:32:27 -070082 REQUIRES(!log_lock_);
Mathieu Chartier38e954c2017-02-03 16:06:35 -080083 void RecordWriteField64(mirror::Object* obj,
84 MemberOffset field_offset,
85 uint64_t value,
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +010086 bool is_volatile)
Mathieu Chartier90443472015-07-16 20:32:27 -070087 REQUIRES(!log_lock_);
Mathieu Chartier38e954c2017-02-03 16:06:35 -080088 void RecordWriteFieldReference(mirror::Object* obj,
89 MemberOffset field_offset,
90 mirror::Object* value,
91 bool is_volatile)
Mathieu Chartier90443472015-07-16 20:32:27 -070092 REQUIRES(!log_lock_);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +010093
94 // Record array change.
95 void RecordWriteArray(mirror::Array* array, size_t index, uint64_t value)
Mathieu Chartier90443472015-07-16 20:32:27 -070096 REQUIRES(!log_lock_)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -070097 REQUIRES_SHARED(Locks::mutator_lock_);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +010098
99 // Record intern string table changes.
Mathieu Chartier9e868092016-10-31 14:58:04 -0700100 void RecordStrongStringInsertion(ObjPtr<mirror::String> s)
Mathieu Chartier90443472015-07-16 20:32:27 -0700101 REQUIRES(Locks::intern_table_lock_)
102 REQUIRES(!log_lock_);
Mathieu Chartier9e868092016-10-31 14:58:04 -0700103 void RecordWeakStringInsertion(ObjPtr<mirror::String> s)
Mathieu Chartier90443472015-07-16 20:32:27 -0700104 REQUIRES(Locks::intern_table_lock_)
105 REQUIRES(!log_lock_);
Mathieu Chartier9e868092016-10-31 14:58:04 -0700106 void RecordStrongStringRemoval(ObjPtr<mirror::String> s)
Mathieu Chartier90443472015-07-16 20:32:27 -0700107 REQUIRES(Locks::intern_table_lock_)
108 REQUIRES(!log_lock_);
Mathieu Chartier9e868092016-10-31 14:58:04 -0700109 void RecordWeakStringRemoval(ObjPtr<mirror::String> s)
Mathieu Chartier90443472015-07-16 20:32:27 -0700110 REQUIRES(Locks::intern_table_lock_)
111 REQUIRES(!log_lock_);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100112
Mathieu Chartierbb816d62016-09-07 10:17:46 -0700113 // Record resolve string.
Andreas Gampe8a0128a2016-11-28 07:38:35 -0800114 void RecordResolveString(ObjPtr<mirror::DexCache> dex_cache, dex::StringIndex string_idx)
Mathieu Chartierbb816d62016-09-07 10:17:46 -0700115 REQUIRES_SHARED(Locks::mutator_lock_)
116 REQUIRES(!log_lock_);
117
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100118 // Abort transaction by undoing all recorded changes.
Sebastien Hertz1c80bec2015-02-03 11:58:06 +0100119 void Rollback()
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700120 REQUIRES_SHARED(Locks::mutator_lock_)
Mathieu Chartier90443472015-07-16 20:32:27 -0700121 REQUIRES(!log_lock_);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100122
Mathieu Chartierbb87e0f2015-04-03 11:21:55 -0700123 void VisitRoots(RootVisitor* visitor)
Mathieu Chartier90443472015-07-16 20:32:27 -0700124 REQUIRES(!log_lock_)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700125 REQUIRES_SHARED(Locks::mutator_lock_);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100126
127 private:
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700128 class ObjectLog : public ValueObject {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100129 public:
Fred Shih37f05ef2014-07-16 18:38:08 -0700130 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);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100134 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
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800138 void Undo(mirror::Object* obj) const REQUIRES_SHARED(Locks::mutator_lock_);
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700139 void VisitRoots(RootVisitor* visitor) REQUIRES_SHARED(Locks::mutator_lock_);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100140
141 size_t Size() const {
142 return field_values_.size();
143 }
144
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800145 ObjectLog() = default;
146 ObjectLog(ObjectLog&& log) = default;
147
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100148 private:
149 enum FieldValueKind {
Fred Shih37f05ef2014-07-16 18:38:08 -0700150 kBoolean,
151 kByte,
152 kChar,
153 kShort,
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100154 k32Bits,
155 k64Bits,
156 kReference
157 };
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700158 struct FieldValue : public ValueObject {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100159 // TODO use JValue instead ?
160 uint64_t value;
161 FieldValueKind kind;
162 bool is_volatile;
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800163
Andreas Gamped9911ee2017-03-27 13:27:24 -0700164 FieldValue() : value(0), kind(FieldValueKind::kBoolean), is_volatile(false) {}
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800165 FieldValue(FieldValue&& log) = default;
166
167 private:
168 DISALLOW_COPY_AND_ASSIGN(FieldValue);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100169 };
170
Fred Shih37f05ef2014-07-16 18:38:08 -0700171 void LogValue(FieldValueKind kind, MemberOffset offset, uint64_t value, bool is_volatile);
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800172 void UndoFieldWrite(mirror::Object* obj,
173 MemberOffset field_offset,
174 const FieldValue& field_value) const REQUIRES_SHARED(Locks::mutator_lock_);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100175
176 // Maps field's offset to its value.
177 std::map<uint32_t, FieldValue> field_values_;
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800178
179 DISALLOW_COPY_AND_ASSIGN(ObjectLog);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100180 };
181
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700182 class ArrayLog : public ValueObject {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100183 public:
184 void LogValue(size_t index, uint64_t value);
185
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800186 void Undo(mirror::Array* obj) const REQUIRES_SHARED(Locks::mutator_lock_);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100187
188 size_t Size() const {
189 return array_values_.size();
190 }
191
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800192 ArrayLog() = default;
193 ArrayLog(ArrayLog&& log) = default;
194
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100195 private:
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800196 void UndoArrayWrite(mirror::Array* array,
197 Primitive::Type array_type,
198 size_t index,
199 uint64_t value) const REQUIRES_SHARED(Locks::mutator_lock_);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100200
201 // Maps index to value.
202 // TODO use JValue instead ?
203 std::map<size_t, uint64_t> array_values_;
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800204
205 DISALLOW_COPY_AND_ASSIGN(ArrayLog);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100206 };
207
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700208 class InternStringLog : public ValueObject {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100209 public:
210 enum StringKind {
211 kStrongString,
212 kWeakString
213 };
214 enum StringOp {
215 kInsert,
216 kRemove
217 };
Mathieu Chartier9e868092016-10-31 14:58:04 -0700218 InternStringLog(ObjPtr<mirror::String> s, StringKind kind, StringOp op);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100219
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800220 void Undo(InternTable* intern_table) const
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700221 REQUIRES_SHARED(Locks::mutator_lock_)
Mathieu Chartier90443472015-07-16 20:32:27 -0700222 REQUIRES(Locks::intern_table_lock_);
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700223 void VisitRoots(RootVisitor* visitor) REQUIRES_SHARED(Locks::mutator_lock_);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100224
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800225 InternStringLog() = default;
226 InternStringLog(InternStringLog&& log) = default;
227
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100228 private:
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800229 mutable GcRoot<mirror::String> str_;
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700230 const StringKind string_kind_;
231 const StringOp string_op_;
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800232
233 DISALLOW_COPY_AND_ASSIGN(InternStringLog);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100234 };
235
Mathieu Chartierbb816d62016-09-07 10:17:46 -0700236 class ResolveStringLog : public ValueObject {
237 public:
Andreas Gampe8a0128a2016-11-28 07:38:35 -0800238 ResolveStringLog(ObjPtr<mirror::DexCache> dex_cache, dex::StringIndex string_idx);
Mathieu Chartierbb816d62016-09-07 10:17:46 -0700239
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800240 void Undo() const REQUIRES_SHARED(Locks::mutator_lock_);
Mathieu Chartierbb816d62016-09-07 10:17:46 -0700241
242 void VisitRoots(RootVisitor* visitor) REQUIRES_SHARED(Locks::mutator_lock_);
243
244 private:
245 GcRoot<mirror::DexCache> dex_cache_;
Andreas Gampe8a0128a2016-11-28 07:38:35 -0800246 const dex::StringIndex string_idx_;
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800247
248 DISALLOW_COPY_AND_ASSIGN(ResolveStringLog);
Mathieu Chartierbb816d62016-09-07 10:17:46 -0700249 };
250
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800251 void LogInternedString(InternStringLog&& log)
Mathieu Chartier90443472015-07-16 20:32:27 -0700252 REQUIRES(Locks::intern_table_lock_)
253 REQUIRES(!log_lock_);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100254
255 void UndoObjectModifications()
Mathieu Chartier90443472015-07-16 20:32:27 -0700256 REQUIRES(log_lock_)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700257 REQUIRES_SHARED(Locks::mutator_lock_);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100258 void UndoArrayModifications()
Mathieu Chartier90443472015-07-16 20:32:27 -0700259 REQUIRES(log_lock_)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700260 REQUIRES_SHARED(Locks::mutator_lock_);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100261 void UndoInternStringTableModifications()
Mathieu Chartier90443472015-07-16 20:32:27 -0700262 REQUIRES(Locks::intern_table_lock_)
263 REQUIRES(log_lock_)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700264 REQUIRES_SHARED(Locks::mutator_lock_);
Mathieu Chartierbb816d62016-09-07 10:17:46 -0700265 void UndoResolveStringModifications()
266 REQUIRES(log_lock_)
267 REQUIRES_SHARED(Locks::mutator_lock_);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100268
Mathieu Chartierbb87e0f2015-04-03 11:21:55 -0700269 void VisitObjectLogs(RootVisitor* visitor)
Mathieu Chartier90443472015-07-16 20:32:27 -0700270 REQUIRES(log_lock_)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700271 REQUIRES_SHARED(Locks::mutator_lock_);
Mathieu Chartierbb87e0f2015-04-03 11:21:55 -0700272 void VisitArrayLogs(RootVisitor* visitor)
Mathieu Chartier90443472015-07-16 20:32:27 -0700273 REQUIRES(log_lock_)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700274 REQUIRES_SHARED(Locks::mutator_lock_);
Mathieu Chartierbb816d62016-09-07 10:17:46 -0700275 void VisitInternStringLogs(RootVisitor* visitor)
276 REQUIRES(log_lock_)
277 REQUIRES_SHARED(Locks::mutator_lock_);
278 void VisitResolveStringLogs(RootVisitor* visitor)
Mathieu Chartier90443472015-07-16 20:32:27 -0700279 REQUIRES(log_lock_)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700280 REQUIRES_SHARED(Locks::mutator_lock_);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100281
Mathieu Chartier90443472015-07-16 20:32:27 -0700282 const std::string& GetAbortMessage() REQUIRES(!log_lock_);
Sebastien Hertz1c80bec2015-02-03 11:58:06 +0100283
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100284 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_);
Mathieu Chartierbb816d62016-09-07 10:17:46 -0700288 std::list<ResolveStringLog> resolve_string_logs_ GUARDED_BY(log_lock_);
Sebastien Hertz1c80bec2015-02-03 11:58:06 +0100289 bool aborted_ GUARDED_BY(log_lock_);
290 std::string abort_message_ GUARDED_BY(log_lock_);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100291
292 DISALLOW_COPY_AND_ASSIGN(Transaction);
293};
294
295} // namespace art
296
297#endif // ART_RUNTIME_TRANSACTION_H_