blob: de6edd2ff3fae47ea4d0c4ec9a4283429c0f1207 [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"
David Sehr67bf42e2018-02-26 16:43:04 -080022#include "base/safe_map.h"
Ian Rogers6a3c1fc2014-10-31 00:33:20 -070023#include "base/value_object.h"
David Sehr9e734c72018-01-04 17:56:19 -080024#include "dex/dex_file_types.h"
David Sehr67bf42e2018-02-26 16:43:04 -080025#include "dex/primitive.h"
Mathieu Chartiere34fa1d2015-01-14 14:55:47 -080026#include "gc_root.h"
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +010027#include "offsets.h"
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +010028
29#include <list>
30#include <map>
31
32namespace art {
33namespace mirror {
34class Array;
Chang Xingcade5c32017-07-20 17:56:26 -070035class Class;
Mathieu Chartierbb816d62016-09-07 10:17:46 -070036class DexCache;
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +010037class Object;
38class String;
Andreas Gampedeae7db2017-05-30 09:56:41 -070039} // namespace mirror
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +010040class InternTable;
41
Roland Levillainbbc6e7e2018-08-24 16:58:47 +010042class 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();
Chang Xing5a906fc2017-07-26 15:01:16 -070048 explicit Transaction(bool strict, mirror::Class* root);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +010049 ~Transaction();
50
Sebastien Hertz1c80bec2015-02-03 11:58:06 +010051 void Abort(const std::string& abort_message)
Mathieu Chartier90443472015-07-16 20:32:27 -070052 REQUIRES(!log_lock_)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -070053 REQUIRES_SHARED(Locks::mutator_lock_);
Sebastien Hertzb81e1cd2015-04-28 12:31:41 +020054 void ThrowAbortError(Thread* self, const std::string* abort_message)
Mathieu Chartier90443472015-07-16 20:32:27 -070055 REQUIRES(!log_lock_)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -070056 REQUIRES_SHARED(Locks::mutator_lock_);
Mathieu Chartier90443472015-07-16 20:32:27 -070057 bool IsAborted() REQUIRES(!log_lock_);
Sebastien Hertz1c80bec2015-02-03 11:58:06 +010058
Chang Xing605fe242017-07-20 15:57:21 -070059 // 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
Chang Xing5a906fc2017-07-26 15:01:16 -070063 // 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
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +010068 // Record object field changes.
Mathieu Chartier38e954c2017-02-03 16:06:35 -080069 void RecordWriteFieldBoolean(mirror::Object* obj,
70 MemberOffset field_offset,
71 uint8_t value,
Fred Shih37f05ef2014-07-16 18:38:08 -070072 bool is_volatile)
Mathieu Chartier90443472015-07-16 20:32:27 -070073 REQUIRES(!log_lock_);
Mathieu Chartier38e954c2017-02-03 16:06:35 -080074 void RecordWriteFieldByte(mirror::Object* obj,
75 MemberOffset field_offset,
76 int8_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 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,
Fred Shih37f05ef2014-07-16 18:38:08 -070087 bool is_volatile)
Mathieu Chartier90443472015-07-16 20:32:27 -070088 REQUIRES(!log_lock_);
Mathieu Chartier38e954c2017-02-03 16:06:35 -080089 void RecordWriteField32(mirror::Object* obj,
90 MemberOffset field_offset,
91 uint32_t value,
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +010092 bool is_volatile)
Mathieu Chartier90443472015-07-16 20:32:27 -070093 REQUIRES(!log_lock_);
Mathieu Chartier38e954c2017-02-03 16:06:35 -080094 void RecordWriteField64(mirror::Object* obj,
95 MemberOffset field_offset,
96 uint64_t value,
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +010097 bool is_volatile)
Mathieu Chartier90443472015-07-16 20:32:27 -070098 REQUIRES(!log_lock_);
Mathieu Chartier38e954c2017-02-03 16:06:35 -080099 void RecordWriteFieldReference(mirror::Object* obj,
100 MemberOffset field_offset,
101 mirror::Object* value,
102 bool is_volatile)
Mathieu Chartier90443472015-07-16 20:32:27 -0700103 REQUIRES(!log_lock_);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100104
105 // Record array change.
106 void RecordWriteArray(mirror::Array* array, size_t index, uint64_t value)
Mathieu Chartier90443472015-07-16 20:32:27 -0700107 REQUIRES(!log_lock_)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700108 REQUIRES_SHARED(Locks::mutator_lock_);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100109
110 // Record intern string table changes.
Mathieu Chartier9e868092016-10-31 14:58:04 -0700111 void RecordStrongStringInsertion(ObjPtr<mirror::String> s)
Mathieu Chartier90443472015-07-16 20:32:27 -0700112 REQUIRES(Locks::intern_table_lock_)
113 REQUIRES(!log_lock_);
Mathieu Chartier9e868092016-10-31 14:58:04 -0700114 void RecordWeakStringInsertion(ObjPtr<mirror::String> s)
Mathieu Chartier90443472015-07-16 20:32:27 -0700115 REQUIRES(Locks::intern_table_lock_)
116 REQUIRES(!log_lock_);
Mathieu Chartier9e868092016-10-31 14:58:04 -0700117 void RecordStrongStringRemoval(ObjPtr<mirror::String> s)
Mathieu Chartier90443472015-07-16 20:32:27 -0700118 REQUIRES(Locks::intern_table_lock_)
119 REQUIRES(!log_lock_);
Mathieu Chartier9e868092016-10-31 14:58:04 -0700120 void RecordWeakStringRemoval(ObjPtr<mirror::String> s)
Mathieu Chartier90443472015-07-16 20:32:27 -0700121 REQUIRES(Locks::intern_table_lock_)
122 REQUIRES(!log_lock_);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100123
Mathieu Chartierbb816d62016-09-07 10:17:46 -0700124 // Record resolve string.
Andreas Gampe8a0128a2016-11-28 07:38:35 -0800125 void RecordResolveString(ObjPtr<mirror::DexCache> dex_cache, dex::StringIndex string_idx)
Mathieu Chartierbb816d62016-09-07 10:17:46 -0700126 REQUIRES_SHARED(Locks::mutator_lock_)
127 REQUIRES(!log_lock_);
128
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100129 // Abort transaction by undoing all recorded changes.
Sebastien Hertz1c80bec2015-02-03 11:58:06 +0100130 void Rollback()
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700131 REQUIRES_SHARED(Locks::mutator_lock_)
Mathieu Chartier90443472015-07-16 20:32:27 -0700132 REQUIRES(!log_lock_);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100133
Mathieu Chartierbb87e0f2015-04-03 11:21:55 -0700134 void VisitRoots(RootVisitor* visitor)
Mathieu Chartier90443472015-07-16 20:32:27 -0700135 REQUIRES(!log_lock_)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700136 REQUIRES_SHARED(Locks::mutator_lock_);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100137
Chang Xingbd208d82017-07-12 14:53:17 -0700138 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
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100146 private:
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700147 class ObjectLog : public ValueObject {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100148 public:
Fred Shih37f05ef2014-07-16 18:38:08 -0700149 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);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100153 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
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800157 void Undo(mirror::Object* obj) const REQUIRES_SHARED(Locks::mutator_lock_);
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700158 void VisitRoots(RootVisitor* visitor) REQUIRES_SHARED(Locks::mutator_lock_);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100159
160 size_t Size() const {
161 return field_values_.size();
162 }
163
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800164 ObjectLog() = default;
165 ObjectLog(ObjectLog&& log) = default;
166
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100167 private:
168 enum FieldValueKind {
Fred Shih37f05ef2014-07-16 18:38:08 -0700169 kBoolean,
170 kByte,
171 kChar,
172 kShort,
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100173 k32Bits,
174 k64Bits,
175 kReference
176 };
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700177 struct FieldValue : public ValueObject {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100178 // TODO use JValue instead ?
179 uint64_t value;
180 FieldValueKind kind;
181 bool is_volatile;
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800182
Andreas Gamped9911ee2017-03-27 13:27:24 -0700183 FieldValue() : value(0), kind(FieldValueKind::kBoolean), is_volatile(false) {}
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800184 FieldValue(FieldValue&& log) = default;
185
186 private:
187 DISALLOW_COPY_AND_ASSIGN(FieldValue);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100188 };
189
Fred Shih37f05ef2014-07-16 18:38:08 -0700190 void LogValue(FieldValueKind kind, MemberOffset offset, uint64_t value, bool is_volatile);
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800191 void UndoFieldWrite(mirror::Object* obj,
192 MemberOffset field_offset,
193 const FieldValue& field_value) const REQUIRES_SHARED(Locks::mutator_lock_);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100194
195 // Maps field's offset to its value.
196 std::map<uint32_t, FieldValue> field_values_;
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800197
198 DISALLOW_COPY_AND_ASSIGN(ObjectLog);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100199 };
200
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700201 class ArrayLog : public ValueObject {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100202 public:
203 void LogValue(size_t index, uint64_t value);
204
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800205 void Undo(mirror::Array* obj) const REQUIRES_SHARED(Locks::mutator_lock_);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100206
207 size_t Size() const {
208 return array_values_.size();
209 }
210
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800211 ArrayLog() = default;
212 ArrayLog(ArrayLog&& log) = default;
213
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100214 private:
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800215 void UndoArrayWrite(mirror::Array* array,
216 Primitive::Type array_type,
217 size_t index,
218 uint64_t value) const REQUIRES_SHARED(Locks::mutator_lock_);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100219
220 // Maps index to value.
221 // TODO use JValue instead ?
222 std::map<size_t, uint64_t> array_values_;
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800223
224 DISALLOW_COPY_AND_ASSIGN(ArrayLog);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100225 };
226
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700227 class InternStringLog : public ValueObject {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100228 public:
229 enum StringKind {
230 kStrongString,
231 kWeakString
232 };
233 enum StringOp {
234 kInsert,
235 kRemove
236 };
Mathieu Chartier9e868092016-10-31 14:58:04 -0700237 InternStringLog(ObjPtr<mirror::String> s, StringKind kind, StringOp op);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100238
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800239 void Undo(InternTable* intern_table) const
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700240 REQUIRES_SHARED(Locks::mutator_lock_)
Mathieu Chartier90443472015-07-16 20:32:27 -0700241 REQUIRES(Locks::intern_table_lock_);
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700242 void VisitRoots(RootVisitor* visitor) REQUIRES_SHARED(Locks::mutator_lock_);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100243
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800244 InternStringLog() = default;
245 InternStringLog(InternStringLog&& log) = default;
246
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100247 private:
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800248 mutable GcRoot<mirror::String> str_;
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700249 const StringKind string_kind_;
250 const StringOp string_op_;
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800251
252 DISALLOW_COPY_AND_ASSIGN(InternStringLog);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100253 };
254
Mathieu Chartierbb816d62016-09-07 10:17:46 -0700255 class ResolveStringLog : public ValueObject {
256 public:
Andreas Gampe8a0128a2016-11-28 07:38:35 -0800257 ResolveStringLog(ObjPtr<mirror::DexCache> dex_cache, dex::StringIndex string_idx);
Mathieu Chartierbb816d62016-09-07 10:17:46 -0700258
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800259 void Undo() const REQUIRES_SHARED(Locks::mutator_lock_);
Mathieu Chartierbb816d62016-09-07 10:17:46 -0700260
261 void VisitRoots(RootVisitor* visitor) REQUIRES_SHARED(Locks::mutator_lock_);
262
263 private:
264 GcRoot<mirror::DexCache> dex_cache_;
Andreas Gampe8a0128a2016-11-28 07:38:35 -0800265 const dex::StringIndex string_idx_;
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800266
267 DISALLOW_COPY_AND_ASSIGN(ResolveStringLog);
Mathieu Chartierbb816d62016-09-07 10:17:46 -0700268 };
269
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800270 void LogInternedString(InternStringLog&& log)
Mathieu Chartier90443472015-07-16 20:32:27 -0700271 REQUIRES(Locks::intern_table_lock_)
272 REQUIRES(!log_lock_);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100273
274 void UndoObjectModifications()
Mathieu Chartier90443472015-07-16 20:32:27 -0700275 REQUIRES(log_lock_)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700276 REQUIRES_SHARED(Locks::mutator_lock_);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100277 void UndoArrayModifications()
Mathieu Chartier90443472015-07-16 20:32:27 -0700278 REQUIRES(log_lock_)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700279 REQUIRES_SHARED(Locks::mutator_lock_);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100280 void UndoInternStringTableModifications()
Mathieu Chartier90443472015-07-16 20:32:27 -0700281 REQUIRES(Locks::intern_table_lock_)
282 REQUIRES(log_lock_)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700283 REQUIRES_SHARED(Locks::mutator_lock_);
Mathieu Chartierbb816d62016-09-07 10:17:46 -0700284 void UndoResolveStringModifications()
285 REQUIRES(log_lock_)
286 REQUIRES_SHARED(Locks::mutator_lock_);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100287
Mathieu Chartierbb87e0f2015-04-03 11:21:55 -0700288 void VisitObjectLogs(RootVisitor* visitor)
Mathieu Chartier90443472015-07-16 20:32:27 -0700289 REQUIRES(log_lock_)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700290 REQUIRES_SHARED(Locks::mutator_lock_);
Mathieu Chartierbb87e0f2015-04-03 11:21:55 -0700291 void VisitArrayLogs(RootVisitor* visitor)
Mathieu Chartier90443472015-07-16 20:32:27 -0700292 REQUIRES(log_lock_)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700293 REQUIRES_SHARED(Locks::mutator_lock_);
Mathieu Chartierbb816d62016-09-07 10:17:46 -0700294 void VisitInternStringLogs(RootVisitor* visitor)
295 REQUIRES(log_lock_)
296 REQUIRES_SHARED(Locks::mutator_lock_);
297 void VisitResolveStringLogs(RootVisitor* visitor)
Mathieu Chartier90443472015-07-16 20:32:27 -0700298 REQUIRES(log_lock_)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700299 REQUIRES_SHARED(Locks::mutator_lock_);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100300
Mathieu Chartier90443472015-07-16 20:32:27 -0700301 const std::string& GetAbortMessage() REQUIRES(!log_lock_);
Sebastien Hertz1c80bec2015-02-03 11:58:06 +0100302
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100303 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_);
Mathieu Chartierbb816d62016-09-07 10:17:46 -0700307 std::list<ResolveStringLog> resolve_string_logs_ GUARDED_BY(log_lock_);
Sebastien Hertz1c80bec2015-02-03 11:58:06 +0100308 bool aborted_ GUARDED_BY(log_lock_);
Chang Xing605fe242017-07-20 15:57:21 -0700309 bool rolling_back_; // Single thread, no race.
Chang Xing5a906fc2017-07-26 15:01:16 -0700310 bool strict_ GUARDED_BY(log_lock_);
Sebastien Hertz1c80bec2015-02-03 11:58:06 +0100311 std::string abort_message_ GUARDED_BY(log_lock_);
Chang Xingcade5c32017-07-20 17:56:26 -0700312 mirror::Class* root_ GUARDED_BY(log_lock_);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100313
314 DISALLOW_COPY_AND_ASSIGN(Transaction);
315};
316
317} // namespace art
318
319#endif // ART_RUNTIME_TRANSACTION_H_