blob: 0333fe8db44bb31a19dc6c75ce7a48ccbc3b5896 [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"
Ian Rogers719d1a32014-03-06 12:13:39 -080025#include "object_callbacks.h"
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +010026#include "offsets.h"
27#include "primitive.h"
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +010028#include "safe_map.h"
29
30#include <list>
31#include <map>
32
33namespace art {
34namespace mirror {
35class Array;
Mathieu Chartierbb816d62016-09-07 10:17:46 -070036class DexCache;
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +010037class Object;
38class String;
39}
40class InternTable;
41
Ian Rogers6a3c1fc2014-10-31 00:33:20 -070042class Transaction FINAL {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +010043 public:
Sebastien Hertz2fd7e692015-04-02 11:11:19 +020044 static constexpr const char* kAbortExceptionDescriptor = "dalvik.system.TransactionAbortError";
45 static constexpr const char* kAbortExceptionSignature = "Ldalvik/system/TransactionAbortError;";
46
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +010047 Transaction();
48 ~Transaction();
49
Sebastien Hertz1c80bec2015-02-03 11:58:06 +010050 void Abort(const std::string& abort_message)
Mathieu Chartier90443472015-07-16 20:32:27 -070051 REQUIRES(!log_lock_)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -070052 REQUIRES_SHARED(Locks::mutator_lock_);
Sebastien Hertzb81e1cd2015-04-28 12:31:41 +020053 void ThrowAbortError(Thread* self, const std::string* abort_message)
Mathieu Chartier90443472015-07-16 20:32:27 -070054 REQUIRES(!log_lock_)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -070055 REQUIRES_SHARED(Locks::mutator_lock_);
Mathieu Chartier90443472015-07-16 20:32:27 -070056 bool IsAborted() REQUIRES(!log_lock_);
Sebastien Hertz1c80bec2015-02-03 11:58:06 +010057
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +010058 // Record object field changes.
Mathieu Chartier38e954c2017-02-03 16:06:35 -080059 void RecordWriteFieldBoolean(mirror::Object* obj,
60 MemberOffset field_offset,
61 uint8_t value,
Fred Shih37f05ef2014-07-16 18:38:08 -070062 bool is_volatile)
Mathieu Chartier90443472015-07-16 20:32:27 -070063 REQUIRES(!log_lock_);
Mathieu Chartier38e954c2017-02-03 16:06:35 -080064 void RecordWriteFieldByte(mirror::Object* obj,
65 MemberOffset field_offset,
66 int8_t value,
Fred Shih37f05ef2014-07-16 18:38:08 -070067 bool is_volatile)
Mathieu Chartier90443472015-07-16 20:32:27 -070068 REQUIRES(!log_lock_);
Mathieu Chartier38e954c2017-02-03 16:06:35 -080069 void RecordWriteFieldChar(mirror::Object* obj,
70 MemberOffset field_offset,
71 uint16_t value,
72 bool is_volatile)
73 REQUIRES(!log_lock_);
74 void RecordWriteFieldShort(mirror::Object* obj,
75 MemberOffset field_offset,
76 int16_t value,
Fred Shih37f05ef2014-07-16 18:38:08 -070077 bool is_volatile)
Mathieu Chartier90443472015-07-16 20:32:27 -070078 REQUIRES(!log_lock_);
Mathieu Chartier38e954c2017-02-03 16:06:35 -080079 void RecordWriteField32(mirror::Object* obj,
80 MemberOffset field_offset,
81 uint32_t value,
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +010082 bool is_volatile)
Mathieu Chartier90443472015-07-16 20:32:27 -070083 REQUIRES(!log_lock_);
Mathieu Chartier38e954c2017-02-03 16:06:35 -080084 void RecordWriteField64(mirror::Object* obj,
85 MemberOffset field_offset,
86 uint64_t value,
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +010087 bool is_volatile)
Mathieu Chartier90443472015-07-16 20:32:27 -070088 REQUIRES(!log_lock_);
Mathieu Chartier38e954c2017-02-03 16:06:35 -080089 void RecordWriteFieldReference(mirror::Object* obj,
90 MemberOffset field_offset,
91 mirror::Object* value,
92 bool is_volatile)
Mathieu Chartier90443472015-07-16 20:32:27 -070093 REQUIRES(!log_lock_);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +010094
95 // Record array change.
96 void RecordWriteArray(mirror::Array* array, size_t index, uint64_t value)
Mathieu Chartier90443472015-07-16 20:32:27 -070097 REQUIRES(!log_lock_)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -070098 REQUIRES_SHARED(Locks::mutator_lock_);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +010099
100 // Record intern string table changes.
Mathieu Chartier9e868092016-10-31 14:58:04 -0700101 void RecordStrongStringInsertion(ObjPtr<mirror::String> s)
Mathieu Chartier90443472015-07-16 20:32:27 -0700102 REQUIRES(Locks::intern_table_lock_)
103 REQUIRES(!log_lock_);
Mathieu Chartier9e868092016-10-31 14:58:04 -0700104 void RecordWeakStringInsertion(ObjPtr<mirror::String> s)
Mathieu Chartier90443472015-07-16 20:32:27 -0700105 REQUIRES(Locks::intern_table_lock_)
106 REQUIRES(!log_lock_);
Mathieu Chartier9e868092016-10-31 14:58:04 -0700107 void RecordStrongStringRemoval(ObjPtr<mirror::String> s)
Mathieu Chartier90443472015-07-16 20:32:27 -0700108 REQUIRES(Locks::intern_table_lock_)
109 REQUIRES(!log_lock_);
Mathieu Chartier9e868092016-10-31 14:58:04 -0700110 void RecordWeakStringRemoval(ObjPtr<mirror::String> s)
Mathieu Chartier90443472015-07-16 20:32:27 -0700111 REQUIRES(Locks::intern_table_lock_)
112 REQUIRES(!log_lock_);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100113
Mathieu Chartierbb816d62016-09-07 10:17:46 -0700114 // Record resolve string.
Andreas Gampe8a0128a2016-11-28 07:38:35 -0800115 void RecordResolveString(ObjPtr<mirror::DexCache> dex_cache, dex::StringIndex string_idx)
Mathieu Chartierbb816d62016-09-07 10:17:46 -0700116 REQUIRES_SHARED(Locks::mutator_lock_)
117 REQUIRES(!log_lock_);
118
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100119 // Abort transaction by undoing all recorded changes.
Sebastien Hertz1c80bec2015-02-03 11:58:06 +0100120 void Rollback()
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700121 REQUIRES_SHARED(Locks::mutator_lock_)
Mathieu Chartier90443472015-07-16 20:32:27 -0700122 REQUIRES(!log_lock_);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100123
Mathieu Chartierbb87e0f2015-04-03 11:21:55 -0700124 void VisitRoots(RootVisitor* visitor)
Mathieu Chartier90443472015-07-16 20:32:27 -0700125 REQUIRES(!log_lock_)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700126 REQUIRES_SHARED(Locks::mutator_lock_);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100127
128 private:
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700129 class ObjectLog : public ValueObject {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100130 public:
Fred Shih37f05ef2014-07-16 18:38:08 -0700131 void LogBooleanValue(MemberOffset offset, uint8_t value, bool is_volatile);
132 void LogByteValue(MemberOffset offset, int8_t value, bool is_volatile);
133 void LogCharValue(MemberOffset offset, uint16_t value, bool is_volatile);
134 void LogShortValue(MemberOffset offset, int16_t value, bool is_volatile);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100135 void Log32BitsValue(MemberOffset offset, uint32_t value, bool is_volatile);
136 void Log64BitsValue(MemberOffset offset, uint64_t value, bool is_volatile);
137 void LogReferenceValue(MemberOffset offset, mirror::Object* obj, bool is_volatile);
138
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800139 void Undo(mirror::Object* obj) const REQUIRES_SHARED(Locks::mutator_lock_);
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700140 void VisitRoots(RootVisitor* visitor) REQUIRES_SHARED(Locks::mutator_lock_);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100141
142 size_t Size() const {
143 return field_values_.size();
144 }
145
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800146 ObjectLog() = default;
147 ObjectLog(ObjectLog&& log) = default;
148
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100149 private:
150 enum FieldValueKind {
Fred Shih37f05ef2014-07-16 18:38:08 -0700151 kBoolean,
152 kByte,
153 kChar,
154 kShort,
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100155 k32Bits,
156 k64Bits,
157 kReference
158 };
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700159 struct FieldValue : public ValueObject {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100160 // TODO use JValue instead ?
161 uint64_t value;
162 FieldValueKind kind;
163 bool is_volatile;
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800164
Andreas Gamped9911ee2017-03-27 13:27:24 -0700165 FieldValue() : value(0), kind(FieldValueKind::kBoolean), is_volatile(false) {}
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800166 FieldValue(FieldValue&& log) = default;
167
168 private:
169 DISALLOW_COPY_AND_ASSIGN(FieldValue);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100170 };
171
Fred Shih37f05ef2014-07-16 18:38:08 -0700172 void LogValue(FieldValueKind kind, MemberOffset offset, uint64_t value, bool is_volatile);
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800173 void UndoFieldWrite(mirror::Object* obj,
174 MemberOffset field_offset,
175 const FieldValue& field_value) const REQUIRES_SHARED(Locks::mutator_lock_);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100176
177 // Maps field's offset to its value.
178 std::map<uint32_t, FieldValue> field_values_;
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800179
180 DISALLOW_COPY_AND_ASSIGN(ObjectLog);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100181 };
182
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700183 class ArrayLog : public ValueObject {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100184 public:
185 void LogValue(size_t index, uint64_t value);
186
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800187 void Undo(mirror::Array* obj) const REQUIRES_SHARED(Locks::mutator_lock_);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100188
189 size_t Size() const {
190 return array_values_.size();
191 }
192
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800193 ArrayLog() = default;
194 ArrayLog(ArrayLog&& log) = default;
195
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100196 private:
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800197 void UndoArrayWrite(mirror::Array* array,
198 Primitive::Type array_type,
199 size_t index,
200 uint64_t value) const REQUIRES_SHARED(Locks::mutator_lock_);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100201
202 // Maps index to value.
203 // TODO use JValue instead ?
204 std::map<size_t, uint64_t> array_values_;
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800205
206 DISALLOW_COPY_AND_ASSIGN(ArrayLog);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100207 };
208
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700209 class InternStringLog : public ValueObject {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100210 public:
211 enum StringKind {
212 kStrongString,
213 kWeakString
214 };
215 enum StringOp {
216 kInsert,
217 kRemove
218 };
Mathieu Chartier9e868092016-10-31 14:58:04 -0700219 InternStringLog(ObjPtr<mirror::String> s, StringKind kind, StringOp op);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100220
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800221 void Undo(InternTable* intern_table) const
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700222 REQUIRES_SHARED(Locks::mutator_lock_)
Mathieu Chartier90443472015-07-16 20:32:27 -0700223 REQUIRES(Locks::intern_table_lock_);
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700224 void VisitRoots(RootVisitor* visitor) REQUIRES_SHARED(Locks::mutator_lock_);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100225
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800226 InternStringLog() = default;
227 InternStringLog(InternStringLog&& log) = default;
228
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100229 private:
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800230 mutable GcRoot<mirror::String> str_;
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700231 const StringKind string_kind_;
232 const StringOp string_op_;
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800233
234 DISALLOW_COPY_AND_ASSIGN(InternStringLog);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100235 };
236
Mathieu Chartierbb816d62016-09-07 10:17:46 -0700237 class ResolveStringLog : public ValueObject {
238 public:
Andreas Gampe8a0128a2016-11-28 07:38:35 -0800239 ResolveStringLog(ObjPtr<mirror::DexCache> dex_cache, dex::StringIndex string_idx);
Mathieu Chartierbb816d62016-09-07 10:17:46 -0700240
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800241 void Undo() const REQUIRES_SHARED(Locks::mutator_lock_);
Mathieu Chartierbb816d62016-09-07 10:17:46 -0700242
243 void VisitRoots(RootVisitor* visitor) REQUIRES_SHARED(Locks::mutator_lock_);
244
245 private:
246 GcRoot<mirror::DexCache> dex_cache_;
Andreas Gampe8a0128a2016-11-28 07:38:35 -0800247 const dex::StringIndex string_idx_;
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800248
249 DISALLOW_COPY_AND_ASSIGN(ResolveStringLog);
Mathieu Chartierbb816d62016-09-07 10:17:46 -0700250 };
251
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800252 void LogInternedString(InternStringLog&& log)
Mathieu Chartier90443472015-07-16 20:32:27 -0700253 REQUIRES(Locks::intern_table_lock_)
254 REQUIRES(!log_lock_);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100255
256 void UndoObjectModifications()
Mathieu Chartier90443472015-07-16 20:32:27 -0700257 REQUIRES(log_lock_)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700258 REQUIRES_SHARED(Locks::mutator_lock_);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100259 void UndoArrayModifications()
Mathieu Chartier90443472015-07-16 20:32:27 -0700260 REQUIRES(log_lock_)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700261 REQUIRES_SHARED(Locks::mutator_lock_);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100262 void UndoInternStringTableModifications()
Mathieu Chartier90443472015-07-16 20:32:27 -0700263 REQUIRES(Locks::intern_table_lock_)
264 REQUIRES(log_lock_)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700265 REQUIRES_SHARED(Locks::mutator_lock_);
Mathieu Chartierbb816d62016-09-07 10:17:46 -0700266 void UndoResolveStringModifications()
267 REQUIRES(log_lock_)
268 REQUIRES_SHARED(Locks::mutator_lock_);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100269
Mathieu Chartierbb87e0f2015-04-03 11:21:55 -0700270 void VisitObjectLogs(RootVisitor* visitor)
Mathieu Chartier90443472015-07-16 20:32:27 -0700271 REQUIRES(log_lock_)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700272 REQUIRES_SHARED(Locks::mutator_lock_);
Mathieu Chartierbb87e0f2015-04-03 11:21:55 -0700273 void VisitArrayLogs(RootVisitor* visitor)
Mathieu Chartier90443472015-07-16 20:32:27 -0700274 REQUIRES(log_lock_)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700275 REQUIRES_SHARED(Locks::mutator_lock_);
Mathieu Chartierbb816d62016-09-07 10:17:46 -0700276 void VisitInternStringLogs(RootVisitor* visitor)
277 REQUIRES(log_lock_)
278 REQUIRES_SHARED(Locks::mutator_lock_);
279 void VisitResolveStringLogs(RootVisitor* visitor)
Mathieu Chartier90443472015-07-16 20:32:27 -0700280 REQUIRES(log_lock_)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700281 REQUIRES_SHARED(Locks::mutator_lock_);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100282
Mathieu Chartier90443472015-07-16 20:32:27 -0700283 const std::string& GetAbortMessage() REQUIRES(!log_lock_);
Sebastien Hertz1c80bec2015-02-03 11:58:06 +0100284
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100285 Mutex log_lock_ ACQUIRED_AFTER(Locks::intern_table_lock_);
286 std::map<mirror::Object*, ObjectLog> object_logs_ GUARDED_BY(log_lock_);
287 std::map<mirror::Array*, ArrayLog> array_logs_ GUARDED_BY(log_lock_);
288 std::list<InternStringLog> intern_string_logs_ GUARDED_BY(log_lock_);
Mathieu Chartierbb816d62016-09-07 10:17:46 -0700289 std::list<ResolveStringLog> resolve_string_logs_ GUARDED_BY(log_lock_);
Sebastien Hertz1c80bec2015-02-03 11:58:06 +0100290 bool aborted_ GUARDED_BY(log_lock_);
291 std::string abort_message_ GUARDED_BY(log_lock_);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100292
293 DISALLOW_COPY_AND_ASSIGN(Transaction);
294};
295
296} // namespace art
297
298#endif // ART_RUNTIME_TRANSACTION_H_