blob: 584dfb8986253e1700677c59c69978dd526d027a [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"
Mathieu Chartiere34fa1d2015-01-14 14:55:47 -080023#include "gc_root.h"
Ian Rogers719d1a32014-03-06 12:13:39 -080024#include "object_callbacks.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;
38}
39class 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.
Fred Shih37f05ef2014-07-16 18:38:08 -070058 void RecordWriteFieldBoolean(mirror::Object* obj, MemberOffset field_offset, uint8_t value,
59 bool is_volatile)
Mathieu Chartier90443472015-07-16 20:32:27 -070060 REQUIRES(!log_lock_);
Fred Shih37f05ef2014-07-16 18:38:08 -070061 void RecordWriteFieldByte(mirror::Object* obj, MemberOffset field_offset, int8_t value,
62 bool is_volatile)
Mathieu Chartier90443472015-07-16 20:32:27 -070063 REQUIRES(!log_lock_);
Fred Shih37f05ef2014-07-16 18:38:08 -070064 void RecordWriteFieldChar(mirror::Object* obj, MemberOffset field_offset, uint16_t value,
65 bool is_volatile)
Mathieu Chartier90443472015-07-16 20:32:27 -070066 REQUIRES(!log_lock_);
Fred Shih37f05ef2014-07-16 18:38:08 -070067 void RecordWriteFieldShort(mirror::Object* obj, MemberOffset field_offset, int16_t value,
68 bool is_volatile)
Mathieu Chartier90443472015-07-16 20:32:27 -070069 REQUIRES(!log_lock_);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +010070 void RecordWriteField32(mirror::Object* obj, MemberOffset field_offset, uint32_t value,
71 bool is_volatile)
Mathieu Chartier90443472015-07-16 20:32:27 -070072 REQUIRES(!log_lock_);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +010073 void RecordWriteField64(mirror::Object* obj, MemberOffset field_offset, uint64_t value,
74 bool is_volatile)
Mathieu Chartier90443472015-07-16 20:32:27 -070075 REQUIRES(!log_lock_);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +010076 void RecordWriteFieldReference(mirror::Object* obj, MemberOffset field_offset,
77 mirror::Object* value, bool is_volatile)
Mathieu Chartier90443472015-07-16 20:32:27 -070078 REQUIRES(!log_lock_);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +010079
80 // Record array change.
81 void RecordWriteArray(mirror::Array* array, size_t index, uint64_t value)
Mathieu Chartier90443472015-07-16 20:32:27 -070082 REQUIRES(!log_lock_)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -070083 REQUIRES_SHARED(Locks::mutator_lock_);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +010084
85 // Record intern string table changes.
Mathieu Chartiercdfd39f2014-08-29 18:16:58 -070086 void RecordStrongStringInsertion(mirror::String* s)
Mathieu Chartier90443472015-07-16 20:32:27 -070087 REQUIRES(Locks::intern_table_lock_)
88 REQUIRES(!log_lock_);
Mathieu Chartiercdfd39f2014-08-29 18:16:58 -070089 void RecordWeakStringInsertion(mirror::String* s)
Mathieu Chartier90443472015-07-16 20:32:27 -070090 REQUIRES(Locks::intern_table_lock_)
91 REQUIRES(!log_lock_);
Mathieu Chartiercdfd39f2014-08-29 18:16:58 -070092 void RecordStrongStringRemoval(mirror::String* s)
Mathieu Chartier90443472015-07-16 20:32:27 -070093 REQUIRES(Locks::intern_table_lock_)
94 REQUIRES(!log_lock_);
Mathieu Chartiercdfd39f2014-08-29 18:16:58 -070095 void RecordWeakStringRemoval(mirror::String* s)
Mathieu Chartier90443472015-07-16 20:32:27 -070096 REQUIRES(Locks::intern_table_lock_)
97 REQUIRES(!log_lock_);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +010098
Mathieu Chartierbb816d62016-09-07 10:17:46 -070099 // Record resolve string.
100 void RecordResolveString(mirror::DexCache* dex_cache, uint32_t string_idx)
101 REQUIRES_SHARED(Locks::mutator_lock_)
102 REQUIRES(!log_lock_);
103
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100104 // Abort transaction by undoing all recorded changes.
Sebastien Hertz1c80bec2015-02-03 11:58:06 +0100105 void Rollback()
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700106 REQUIRES_SHARED(Locks::mutator_lock_)
Mathieu Chartier90443472015-07-16 20:32:27 -0700107 REQUIRES(!log_lock_);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100108
Mathieu Chartierbb87e0f2015-04-03 11:21:55 -0700109 void VisitRoots(RootVisitor* visitor)
Mathieu Chartier90443472015-07-16 20:32:27 -0700110 REQUIRES(!log_lock_)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700111 REQUIRES_SHARED(Locks::mutator_lock_);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100112
113 private:
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700114 class ObjectLog : public ValueObject {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100115 public:
Fred Shih37f05ef2014-07-16 18:38:08 -0700116 void LogBooleanValue(MemberOffset offset, uint8_t value, bool is_volatile);
117 void LogByteValue(MemberOffset offset, int8_t value, bool is_volatile);
118 void LogCharValue(MemberOffset offset, uint16_t value, bool is_volatile);
119 void LogShortValue(MemberOffset offset, int16_t value, bool is_volatile);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100120 void Log32BitsValue(MemberOffset offset, uint32_t value, bool is_volatile);
121 void Log64BitsValue(MemberOffset offset, uint64_t value, bool is_volatile);
122 void LogReferenceValue(MemberOffset offset, mirror::Object* obj, bool is_volatile);
123
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700124 void Undo(mirror::Object* obj) REQUIRES_SHARED(Locks::mutator_lock_);
125 void VisitRoots(RootVisitor* visitor) REQUIRES_SHARED(Locks::mutator_lock_);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100126
127 size_t Size() const {
128 return field_values_.size();
129 }
130
131 private:
132 enum FieldValueKind {
Fred Shih37f05ef2014-07-16 18:38:08 -0700133 kBoolean,
134 kByte,
135 kChar,
136 kShort,
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100137 k32Bits,
138 k64Bits,
139 kReference
140 };
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700141 struct FieldValue : public ValueObject {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100142 // TODO use JValue instead ?
143 uint64_t value;
144 FieldValueKind kind;
145 bool is_volatile;
146 };
147
Fred Shih37f05ef2014-07-16 18:38:08 -0700148 void LogValue(FieldValueKind kind, MemberOffset offset, uint64_t value, bool is_volatile);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100149 void UndoFieldWrite(mirror::Object* obj, MemberOffset field_offset,
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700150 const FieldValue& field_value) REQUIRES_SHARED(Locks::mutator_lock_);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100151
152 // Maps field's offset to its value.
153 std::map<uint32_t, FieldValue> field_values_;
154 };
155
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700156 class ArrayLog : public ValueObject {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100157 public:
158 void LogValue(size_t index, uint64_t value);
159
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700160 void Undo(mirror::Array* obj) REQUIRES_SHARED(Locks::mutator_lock_);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100161
162 size_t Size() const {
163 return array_values_.size();
164 }
165
166 private:
167 void UndoArrayWrite(mirror::Array* array, Primitive::Type array_type, size_t index,
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700168 uint64_t value) REQUIRES_SHARED(Locks::mutator_lock_);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100169
170 // Maps index to value.
171 // TODO use JValue instead ?
172 std::map<size_t, uint64_t> array_values_;
173 };
174
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700175 class InternStringLog : public ValueObject {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100176 public:
177 enum StringKind {
178 kStrongString,
179 kWeakString
180 };
181 enum StringOp {
182 kInsert,
183 kRemove
184 };
Mathieu Chartiercdfd39f2014-08-29 18:16:58 -0700185 InternStringLog(mirror::String* s, StringKind kind, StringOp op)
186 : str_(s), string_kind_(kind), string_op_(op) {
Sebastien Hertzee1d79a2014-02-21 15:46:30 +0100187 DCHECK(s != nullptr);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100188 }
189
Hiroshi Yamauchi1bd48722014-05-23 19:58:15 -0700190 void Undo(InternTable* intern_table)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700191 REQUIRES_SHARED(Locks::mutator_lock_)
Mathieu Chartier90443472015-07-16 20:32:27 -0700192 REQUIRES(Locks::intern_table_lock_);
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700193 void VisitRoots(RootVisitor* visitor) REQUIRES_SHARED(Locks::mutator_lock_);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100194
195 private:
196 mirror::String* str_;
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700197 const StringKind string_kind_;
198 const StringOp string_op_;
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100199 };
200
Mathieu Chartierbb816d62016-09-07 10:17:46 -0700201 class ResolveStringLog : public ValueObject {
202 public:
203 ResolveStringLog(mirror::DexCache* dex_cache, uint32_t string_idx);
204
205 void Undo() REQUIRES_SHARED(Locks::mutator_lock_);
206
207 void VisitRoots(RootVisitor* visitor) REQUIRES_SHARED(Locks::mutator_lock_);
208
209 private:
210 GcRoot<mirror::DexCache> dex_cache_;
211 const uint32_t string_idx_;
212 };
213
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700214 void LogInternedString(const InternStringLog& log)
Mathieu Chartier90443472015-07-16 20:32:27 -0700215 REQUIRES(Locks::intern_table_lock_)
216 REQUIRES(!log_lock_);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100217
218 void UndoObjectModifications()
Mathieu Chartier90443472015-07-16 20:32:27 -0700219 REQUIRES(log_lock_)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700220 REQUIRES_SHARED(Locks::mutator_lock_);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100221 void UndoArrayModifications()
Mathieu Chartier90443472015-07-16 20:32:27 -0700222 REQUIRES(log_lock_)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700223 REQUIRES_SHARED(Locks::mutator_lock_);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100224 void UndoInternStringTableModifications()
Mathieu Chartier90443472015-07-16 20:32:27 -0700225 REQUIRES(Locks::intern_table_lock_)
226 REQUIRES(log_lock_)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700227 REQUIRES_SHARED(Locks::mutator_lock_);
Mathieu Chartierbb816d62016-09-07 10:17:46 -0700228 void UndoResolveStringModifications()
229 REQUIRES(log_lock_)
230 REQUIRES_SHARED(Locks::mutator_lock_);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100231
Mathieu Chartierbb87e0f2015-04-03 11:21:55 -0700232 void VisitObjectLogs(RootVisitor* visitor)
Mathieu Chartier90443472015-07-16 20:32:27 -0700233 REQUIRES(log_lock_)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700234 REQUIRES_SHARED(Locks::mutator_lock_);
Mathieu Chartierbb87e0f2015-04-03 11:21:55 -0700235 void VisitArrayLogs(RootVisitor* visitor)
Mathieu Chartier90443472015-07-16 20:32:27 -0700236 REQUIRES(log_lock_)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700237 REQUIRES_SHARED(Locks::mutator_lock_);
Mathieu Chartierbb816d62016-09-07 10:17:46 -0700238 void VisitInternStringLogs(RootVisitor* visitor)
239 REQUIRES(log_lock_)
240 REQUIRES_SHARED(Locks::mutator_lock_);
241 void VisitResolveStringLogs(RootVisitor* visitor)
Mathieu Chartier90443472015-07-16 20:32:27 -0700242 REQUIRES(log_lock_)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700243 REQUIRES_SHARED(Locks::mutator_lock_);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100244
Mathieu Chartier90443472015-07-16 20:32:27 -0700245 const std::string& GetAbortMessage() REQUIRES(!log_lock_);
Sebastien Hertz1c80bec2015-02-03 11:58:06 +0100246
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100247 Mutex log_lock_ ACQUIRED_AFTER(Locks::intern_table_lock_);
248 std::map<mirror::Object*, ObjectLog> object_logs_ GUARDED_BY(log_lock_);
249 std::map<mirror::Array*, ArrayLog> array_logs_ GUARDED_BY(log_lock_);
250 std::list<InternStringLog> intern_string_logs_ GUARDED_BY(log_lock_);
Mathieu Chartierbb816d62016-09-07 10:17:46 -0700251 std::list<ResolveStringLog> resolve_string_logs_ GUARDED_BY(log_lock_);
Sebastien Hertz1c80bec2015-02-03 11:58:06 +0100252 bool aborted_ GUARDED_BY(log_lock_);
253 std::string abort_message_ GUARDED_BY(log_lock_);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100254
255 DISALLOW_COPY_AND_ASSIGN(Transaction);
256};
257
258} // namespace art
259
260#endif // ART_RUNTIME_TRANSACTION_H_