blob: 1774657d40428745500686d7146df23f3192f227 [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.
Fred Shih37f05ef2014-07-16 18:38:08 -070059 void RecordWriteFieldBoolean(mirror::Object* obj, MemberOffset field_offset, uint8_t value,
60 bool is_volatile)
Mathieu Chartier90443472015-07-16 20:32:27 -070061 REQUIRES(!log_lock_);
Fred Shih37f05ef2014-07-16 18:38:08 -070062 void RecordWriteFieldByte(mirror::Object* obj, MemberOffset field_offset, int8_t value,
63 bool is_volatile)
Mathieu Chartier90443472015-07-16 20:32:27 -070064 REQUIRES(!log_lock_);
Fred Shih37f05ef2014-07-16 18:38:08 -070065 void RecordWriteFieldChar(mirror::Object* obj, MemberOffset field_offset, uint16_t value,
66 bool is_volatile)
Mathieu Chartier90443472015-07-16 20:32:27 -070067 REQUIRES(!log_lock_);
Fred Shih37f05ef2014-07-16 18:38:08 -070068 void RecordWriteFieldShort(mirror::Object* obj, MemberOffset field_offset, int16_t value,
69 bool is_volatile)
Mathieu Chartier90443472015-07-16 20:32:27 -070070 REQUIRES(!log_lock_);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +010071 void RecordWriteField32(mirror::Object* obj, MemberOffset field_offset, uint32_t value,
72 bool is_volatile)
Mathieu Chartier90443472015-07-16 20:32:27 -070073 REQUIRES(!log_lock_);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +010074 void RecordWriteField64(mirror::Object* obj, MemberOffset field_offset, uint64_t value,
75 bool is_volatile)
Mathieu Chartier90443472015-07-16 20:32:27 -070076 REQUIRES(!log_lock_);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +010077 void RecordWriteFieldReference(mirror::Object* obj, MemberOffset field_offset,
78 mirror::Object* value, bool is_volatile)
Mathieu Chartier90443472015-07-16 20:32:27 -070079 REQUIRES(!log_lock_);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +010080
81 // Record array change.
82 void RecordWriteArray(mirror::Array* array, size_t index, uint64_t value)
Mathieu Chartier90443472015-07-16 20:32:27 -070083 REQUIRES(!log_lock_)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -070084 REQUIRES_SHARED(Locks::mutator_lock_);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +010085
86 // Record intern string table changes.
Mathieu Chartier9e868092016-10-31 14:58:04 -070087 void RecordStrongStringInsertion(ObjPtr<mirror::String> s)
Mathieu Chartier90443472015-07-16 20:32:27 -070088 REQUIRES(Locks::intern_table_lock_)
89 REQUIRES(!log_lock_);
Mathieu Chartier9e868092016-10-31 14:58:04 -070090 void RecordWeakStringInsertion(ObjPtr<mirror::String> s)
Mathieu Chartier90443472015-07-16 20:32:27 -070091 REQUIRES(Locks::intern_table_lock_)
92 REQUIRES(!log_lock_);
Mathieu Chartier9e868092016-10-31 14:58:04 -070093 void RecordStrongStringRemoval(ObjPtr<mirror::String> s)
Mathieu Chartier90443472015-07-16 20:32:27 -070094 REQUIRES(Locks::intern_table_lock_)
95 REQUIRES(!log_lock_);
Mathieu Chartier9e868092016-10-31 14:58:04 -070096 void RecordWeakStringRemoval(ObjPtr<mirror::String> s)
Mathieu Chartier90443472015-07-16 20:32:27 -070097 REQUIRES(Locks::intern_table_lock_)
98 REQUIRES(!log_lock_);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +010099
Mathieu Chartierbb816d62016-09-07 10:17:46 -0700100 // Record resolve string.
Andreas Gampe8a0128a2016-11-28 07:38:35 -0800101 void RecordResolveString(ObjPtr<mirror::DexCache> dex_cache, dex::StringIndex string_idx)
Mathieu Chartierbb816d62016-09-07 10:17:46 -0700102 REQUIRES_SHARED(Locks::mutator_lock_)
103 REQUIRES(!log_lock_);
104
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100105 // Abort transaction by undoing all recorded changes.
Sebastien Hertz1c80bec2015-02-03 11:58:06 +0100106 void Rollback()
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700107 REQUIRES_SHARED(Locks::mutator_lock_)
Mathieu Chartier90443472015-07-16 20:32:27 -0700108 REQUIRES(!log_lock_);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100109
Mathieu Chartierbb87e0f2015-04-03 11:21:55 -0700110 void VisitRoots(RootVisitor* visitor)
Mathieu Chartier90443472015-07-16 20:32:27 -0700111 REQUIRES(!log_lock_)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700112 REQUIRES_SHARED(Locks::mutator_lock_);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100113
114 private:
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700115 class ObjectLog : public ValueObject {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100116 public:
Fred Shih37f05ef2014-07-16 18:38:08 -0700117 void LogBooleanValue(MemberOffset offset, uint8_t value, bool is_volatile);
118 void LogByteValue(MemberOffset offset, int8_t value, bool is_volatile);
119 void LogCharValue(MemberOffset offset, uint16_t value, bool is_volatile);
120 void LogShortValue(MemberOffset offset, int16_t value, bool is_volatile);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100121 void Log32BitsValue(MemberOffset offset, uint32_t value, bool is_volatile);
122 void Log64BitsValue(MemberOffset offset, uint64_t value, bool is_volatile);
123 void LogReferenceValue(MemberOffset offset, mirror::Object* obj, bool is_volatile);
124
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700125 void Undo(mirror::Object* obj) REQUIRES_SHARED(Locks::mutator_lock_);
126 void VisitRoots(RootVisitor* visitor) REQUIRES_SHARED(Locks::mutator_lock_);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100127
128 size_t Size() const {
129 return field_values_.size();
130 }
131
132 private:
133 enum FieldValueKind {
Fred Shih37f05ef2014-07-16 18:38:08 -0700134 kBoolean,
135 kByte,
136 kChar,
137 kShort,
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100138 k32Bits,
139 k64Bits,
140 kReference
141 };
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700142 struct FieldValue : public ValueObject {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100143 // TODO use JValue instead ?
144 uint64_t value;
145 FieldValueKind kind;
146 bool is_volatile;
147 };
148
Fred Shih37f05ef2014-07-16 18:38:08 -0700149 void LogValue(FieldValueKind kind, MemberOffset offset, uint64_t value, bool is_volatile);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100150 void UndoFieldWrite(mirror::Object* obj, MemberOffset field_offset,
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700151 const FieldValue& field_value) REQUIRES_SHARED(Locks::mutator_lock_);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100152
153 // Maps field's offset to its value.
154 std::map<uint32_t, FieldValue> field_values_;
155 };
156
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700157 class ArrayLog : public ValueObject {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100158 public:
159 void LogValue(size_t index, uint64_t value);
160
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700161 void Undo(mirror::Array* obj) REQUIRES_SHARED(Locks::mutator_lock_);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100162
163 size_t Size() const {
164 return array_values_.size();
165 }
166
167 private:
168 void UndoArrayWrite(mirror::Array* array, Primitive::Type array_type, size_t index,
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700169 uint64_t value) REQUIRES_SHARED(Locks::mutator_lock_);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100170
171 // Maps index to value.
172 // TODO use JValue instead ?
173 std::map<size_t, uint64_t> array_values_;
174 };
175
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700176 class InternStringLog : public ValueObject {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100177 public:
178 enum StringKind {
179 kStrongString,
180 kWeakString
181 };
182 enum StringOp {
183 kInsert,
184 kRemove
185 };
Mathieu Chartier9e868092016-10-31 14:58:04 -0700186 InternStringLog(ObjPtr<mirror::String> s, StringKind kind, StringOp op);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100187
Hiroshi Yamauchi1bd48722014-05-23 19:58:15 -0700188 void Undo(InternTable* intern_table)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700189 REQUIRES_SHARED(Locks::mutator_lock_)
Mathieu Chartier90443472015-07-16 20:32:27 -0700190 REQUIRES(Locks::intern_table_lock_);
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700191 void VisitRoots(RootVisitor* visitor) REQUIRES_SHARED(Locks::mutator_lock_);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100192
193 private:
Mathieu Chartier9e868092016-10-31 14:58:04 -0700194 GcRoot<mirror::String> str_;
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700195 const StringKind string_kind_;
196 const StringOp string_op_;
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100197 };
198
Mathieu Chartierbb816d62016-09-07 10:17:46 -0700199 class ResolveStringLog : public ValueObject {
200 public:
Andreas Gampe8a0128a2016-11-28 07:38:35 -0800201 ResolveStringLog(ObjPtr<mirror::DexCache> dex_cache, dex::StringIndex string_idx);
Mathieu Chartierbb816d62016-09-07 10:17:46 -0700202
203 void Undo() REQUIRES_SHARED(Locks::mutator_lock_);
204
205 void VisitRoots(RootVisitor* visitor) REQUIRES_SHARED(Locks::mutator_lock_);
206
207 private:
208 GcRoot<mirror::DexCache> dex_cache_;
Andreas Gampe8a0128a2016-11-28 07:38:35 -0800209 const dex::StringIndex string_idx_;
Mathieu Chartierbb816d62016-09-07 10:17:46 -0700210 };
211
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700212 void LogInternedString(const InternStringLog& log)
Mathieu Chartier90443472015-07-16 20:32:27 -0700213 REQUIRES(Locks::intern_table_lock_)
214 REQUIRES(!log_lock_);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100215
216 void UndoObjectModifications()
Mathieu Chartier90443472015-07-16 20:32:27 -0700217 REQUIRES(log_lock_)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700218 REQUIRES_SHARED(Locks::mutator_lock_);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100219 void UndoArrayModifications()
Mathieu Chartier90443472015-07-16 20:32:27 -0700220 REQUIRES(log_lock_)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700221 REQUIRES_SHARED(Locks::mutator_lock_);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100222 void UndoInternStringTableModifications()
Mathieu Chartier90443472015-07-16 20:32:27 -0700223 REQUIRES(Locks::intern_table_lock_)
224 REQUIRES(log_lock_)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700225 REQUIRES_SHARED(Locks::mutator_lock_);
Mathieu Chartierbb816d62016-09-07 10:17:46 -0700226 void UndoResolveStringModifications()
227 REQUIRES(log_lock_)
228 REQUIRES_SHARED(Locks::mutator_lock_);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100229
Mathieu Chartierbb87e0f2015-04-03 11:21:55 -0700230 void VisitObjectLogs(RootVisitor* visitor)
Mathieu Chartier90443472015-07-16 20:32:27 -0700231 REQUIRES(log_lock_)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700232 REQUIRES_SHARED(Locks::mutator_lock_);
Mathieu Chartierbb87e0f2015-04-03 11:21:55 -0700233 void VisitArrayLogs(RootVisitor* visitor)
Mathieu Chartier90443472015-07-16 20:32:27 -0700234 REQUIRES(log_lock_)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700235 REQUIRES_SHARED(Locks::mutator_lock_);
Mathieu Chartierbb816d62016-09-07 10:17:46 -0700236 void VisitInternStringLogs(RootVisitor* visitor)
237 REQUIRES(log_lock_)
238 REQUIRES_SHARED(Locks::mutator_lock_);
239 void VisitResolveStringLogs(RootVisitor* visitor)
Mathieu Chartier90443472015-07-16 20:32:27 -0700240 REQUIRES(log_lock_)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700241 REQUIRES_SHARED(Locks::mutator_lock_);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100242
Mathieu Chartier90443472015-07-16 20:32:27 -0700243 const std::string& GetAbortMessage() REQUIRES(!log_lock_);
Sebastien Hertz1c80bec2015-02-03 11:58:06 +0100244
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100245 Mutex log_lock_ ACQUIRED_AFTER(Locks::intern_table_lock_);
246 std::map<mirror::Object*, ObjectLog> object_logs_ GUARDED_BY(log_lock_);
247 std::map<mirror::Array*, ArrayLog> array_logs_ GUARDED_BY(log_lock_);
248 std::list<InternStringLog> intern_string_logs_ GUARDED_BY(log_lock_);
Mathieu Chartierbb816d62016-09-07 10:17:46 -0700249 std::list<ResolveStringLog> resolve_string_logs_ GUARDED_BY(log_lock_);
Sebastien Hertz1c80bec2015-02-03 11:58:06 +0100250 bool aborted_ GUARDED_BY(log_lock_);
251 std::string abort_message_ GUARDED_BY(log_lock_);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100252
253 DISALLOW_COPY_AND_ASSIGN(Transaction);
254};
255
256} // namespace art
257
258#endif // ART_RUNTIME_TRANSACTION_H_