blob: 8ff061457407c20d3b73a04ccca532e365fd7e22 [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;
35class Object;
36class String;
37}
38class InternTable;
39
Ian Rogers6a3c1fc2014-10-31 00:33:20 -070040class Transaction FINAL {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +010041 public:
Sebastien Hertz2fd7e692015-04-02 11:11:19 +020042 static constexpr const char* kAbortExceptionDescriptor = "dalvik.system.TransactionAbortError";
43 static constexpr const char* kAbortExceptionSignature = "Ldalvik/system/TransactionAbortError;";
44
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +010045 Transaction();
46 ~Transaction();
47
Sebastien Hertz1c80bec2015-02-03 11:58:06 +010048 void Abort(const std::string& abort_message)
Mathieu Chartier90443472015-07-16 20:32:27 -070049 REQUIRES(!log_lock_)
50 SHARED_REQUIRES(Locks::mutator_lock_);
Sebastien Hertzb81e1cd2015-04-28 12:31:41 +020051 void ThrowAbortError(Thread* self, const std::string* abort_message)
Mathieu Chartier90443472015-07-16 20:32:27 -070052 REQUIRES(!log_lock_)
53 SHARED_REQUIRES(Locks::mutator_lock_);
54 bool IsAborted() REQUIRES(!log_lock_);
Sebastien Hertz1c80bec2015-02-03 11:58:06 +010055
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +010056 // Record object field changes.
Fred Shih37f05ef2014-07-16 18:38:08 -070057 void RecordWriteFieldBoolean(mirror::Object* obj, MemberOffset field_offset, uint8_t value,
58 bool is_volatile)
Mathieu Chartier90443472015-07-16 20:32:27 -070059 REQUIRES(!log_lock_);
Fred Shih37f05ef2014-07-16 18:38:08 -070060 void RecordWriteFieldByte(mirror::Object* obj, MemberOffset field_offset, int8_t value,
61 bool is_volatile)
Mathieu Chartier90443472015-07-16 20:32:27 -070062 REQUIRES(!log_lock_);
Fred Shih37f05ef2014-07-16 18:38:08 -070063 void RecordWriteFieldChar(mirror::Object* obj, MemberOffset field_offset, uint16_t value,
64 bool is_volatile)
Mathieu Chartier90443472015-07-16 20:32:27 -070065 REQUIRES(!log_lock_);
Fred Shih37f05ef2014-07-16 18:38:08 -070066 void RecordWriteFieldShort(mirror::Object* obj, MemberOffset field_offset, int16_t value,
67 bool is_volatile)
Mathieu Chartier90443472015-07-16 20:32:27 -070068 REQUIRES(!log_lock_);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +010069 void RecordWriteField32(mirror::Object* obj, MemberOffset field_offset, uint32_t value,
70 bool is_volatile)
Mathieu Chartier90443472015-07-16 20:32:27 -070071 REQUIRES(!log_lock_);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +010072 void RecordWriteField64(mirror::Object* obj, MemberOffset field_offset, uint64_t value,
73 bool is_volatile)
Mathieu Chartier90443472015-07-16 20:32:27 -070074 REQUIRES(!log_lock_);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +010075 void RecordWriteFieldReference(mirror::Object* obj, MemberOffset field_offset,
76 mirror::Object* value, bool is_volatile)
Mathieu Chartier90443472015-07-16 20:32:27 -070077 REQUIRES(!log_lock_);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +010078
79 // Record array change.
80 void RecordWriteArray(mirror::Array* array, size_t index, uint64_t value)
Mathieu Chartier90443472015-07-16 20:32:27 -070081 REQUIRES(!log_lock_)
82 SHARED_REQUIRES(Locks::mutator_lock_);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +010083
84 // Record intern string table changes.
Mathieu Chartiercdfd39f2014-08-29 18:16:58 -070085 void RecordStrongStringInsertion(mirror::String* s)
Mathieu Chartier90443472015-07-16 20:32:27 -070086 REQUIRES(Locks::intern_table_lock_)
87 REQUIRES(!log_lock_);
Mathieu Chartiercdfd39f2014-08-29 18:16:58 -070088 void RecordWeakStringInsertion(mirror::String* s)
Mathieu Chartier90443472015-07-16 20:32:27 -070089 REQUIRES(Locks::intern_table_lock_)
90 REQUIRES(!log_lock_);
Mathieu Chartiercdfd39f2014-08-29 18:16:58 -070091 void RecordStrongStringRemoval(mirror::String* s)
Mathieu Chartier90443472015-07-16 20:32:27 -070092 REQUIRES(Locks::intern_table_lock_)
93 REQUIRES(!log_lock_);
Mathieu Chartiercdfd39f2014-08-29 18:16:58 -070094 void RecordWeakStringRemoval(mirror::String* s)
Mathieu Chartier90443472015-07-16 20:32:27 -070095 REQUIRES(Locks::intern_table_lock_)
96 REQUIRES(!log_lock_);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +010097
98 // Abort transaction by undoing all recorded changes.
Sebastien Hertz1c80bec2015-02-03 11:58:06 +010099 void Rollback()
Mathieu Chartier90443472015-07-16 20:32:27 -0700100 SHARED_REQUIRES(Locks::mutator_lock_)
101 REQUIRES(!log_lock_);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100102
Mathieu Chartierbb87e0f2015-04-03 11:21:55 -0700103 void VisitRoots(RootVisitor* visitor)
Mathieu Chartier90443472015-07-16 20:32:27 -0700104 REQUIRES(!log_lock_)
105 SHARED_REQUIRES(Locks::mutator_lock_);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100106
107 private:
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700108 class ObjectLog : public ValueObject {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100109 public:
Fred Shih37f05ef2014-07-16 18:38:08 -0700110 void LogBooleanValue(MemberOffset offset, uint8_t value, bool is_volatile);
111 void LogByteValue(MemberOffset offset, int8_t value, bool is_volatile);
112 void LogCharValue(MemberOffset offset, uint16_t value, bool is_volatile);
113 void LogShortValue(MemberOffset offset, int16_t value, bool is_volatile);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100114 void Log32BitsValue(MemberOffset offset, uint32_t value, bool is_volatile);
115 void Log64BitsValue(MemberOffset offset, uint64_t value, bool is_volatile);
116 void LogReferenceValue(MemberOffset offset, mirror::Object* obj, bool is_volatile);
117
Mathieu Chartier90443472015-07-16 20:32:27 -0700118 void Undo(mirror::Object* obj) SHARED_REQUIRES(Locks::mutator_lock_);
119 void VisitRoots(RootVisitor* visitor) SHARED_REQUIRES(Locks::mutator_lock_);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100120
121 size_t Size() const {
122 return field_values_.size();
123 }
124
125 private:
126 enum FieldValueKind {
Fred Shih37f05ef2014-07-16 18:38:08 -0700127 kBoolean,
128 kByte,
129 kChar,
130 kShort,
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100131 k32Bits,
132 k64Bits,
133 kReference
134 };
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700135 struct FieldValue : public ValueObject {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100136 // TODO use JValue instead ?
137 uint64_t value;
138 FieldValueKind kind;
139 bool is_volatile;
140 };
141
Fred Shih37f05ef2014-07-16 18:38:08 -0700142 void LogValue(FieldValueKind kind, MemberOffset offset, uint64_t value, bool is_volatile);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100143 void UndoFieldWrite(mirror::Object* obj, MemberOffset field_offset,
Mathieu Chartier90443472015-07-16 20:32:27 -0700144 const FieldValue& field_value) SHARED_REQUIRES(Locks::mutator_lock_);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100145
146 // Maps field's offset to its value.
147 std::map<uint32_t, FieldValue> field_values_;
148 };
149
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700150 class ArrayLog : public ValueObject {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100151 public:
152 void LogValue(size_t index, uint64_t value);
153
Mathieu Chartier90443472015-07-16 20:32:27 -0700154 void Undo(mirror::Array* obj) SHARED_REQUIRES(Locks::mutator_lock_);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100155
156 size_t Size() const {
157 return array_values_.size();
158 }
159
160 private:
161 void UndoArrayWrite(mirror::Array* array, Primitive::Type array_type, size_t index,
Mathieu Chartier90443472015-07-16 20:32:27 -0700162 uint64_t value) SHARED_REQUIRES(Locks::mutator_lock_);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100163
164 // Maps index to value.
165 // TODO use JValue instead ?
166 std::map<size_t, uint64_t> array_values_;
167 };
168
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700169 class InternStringLog : public ValueObject {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100170 public:
171 enum StringKind {
172 kStrongString,
173 kWeakString
174 };
175 enum StringOp {
176 kInsert,
177 kRemove
178 };
Mathieu Chartiercdfd39f2014-08-29 18:16:58 -0700179 InternStringLog(mirror::String* s, StringKind kind, StringOp op)
180 : str_(s), string_kind_(kind), string_op_(op) {
Sebastien Hertzee1d79a2014-02-21 15:46:30 +0100181 DCHECK(s != nullptr);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100182 }
183
Hiroshi Yamauchi1bd48722014-05-23 19:58:15 -0700184 void Undo(InternTable* intern_table)
Mathieu Chartier90443472015-07-16 20:32:27 -0700185 SHARED_REQUIRES(Locks::mutator_lock_)
186 REQUIRES(Locks::intern_table_lock_);
187 void VisitRoots(RootVisitor* visitor) SHARED_REQUIRES(Locks::mutator_lock_);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100188
189 private:
190 mirror::String* str_;
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700191 const StringKind string_kind_;
192 const StringOp string_op_;
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100193 };
194
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700195 void LogInternedString(const InternStringLog& log)
Mathieu Chartier90443472015-07-16 20:32:27 -0700196 REQUIRES(Locks::intern_table_lock_)
197 REQUIRES(!log_lock_);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100198
199 void UndoObjectModifications()
Mathieu Chartier90443472015-07-16 20:32:27 -0700200 REQUIRES(log_lock_)
201 SHARED_REQUIRES(Locks::mutator_lock_);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100202 void UndoArrayModifications()
Mathieu Chartier90443472015-07-16 20:32:27 -0700203 REQUIRES(log_lock_)
204 SHARED_REQUIRES(Locks::mutator_lock_);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100205 void UndoInternStringTableModifications()
Mathieu Chartier90443472015-07-16 20:32:27 -0700206 REQUIRES(Locks::intern_table_lock_)
207 REQUIRES(log_lock_)
208 SHARED_REQUIRES(Locks::mutator_lock_);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100209
Mathieu Chartierbb87e0f2015-04-03 11:21:55 -0700210 void VisitObjectLogs(RootVisitor* visitor)
Mathieu Chartier90443472015-07-16 20:32:27 -0700211 REQUIRES(log_lock_)
212 SHARED_REQUIRES(Locks::mutator_lock_);
Mathieu Chartierbb87e0f2015-04-03 11:21:55 -0700213 void VisitArrayLogs(RootVisitor* visitor)
Mathieu Chartier90443472015-07-16 20:32:27 -0700214 REQUIRES(log_lock_)
215 SHARED_REQUIRES(Locks::mutator_lock_);
Mathieu Chartierbb87e0f2015-04-03 11:21:55 -0700216 void VisitStringLogs(RootVisitor* visitor)
Mathieu Chartier90443472015-07-16 20:32:27 -0700217 REQUIRES(log_lock_)
218 SHARED_REQUIRES(Locks::mutator_lock_);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100219
Mathieu Chartier90443472015-07-16 20:32:27 -0700220 const std::string& GetAbortMessage() REQUIRES(!log_lock_);
Sebastien Hertz1c80bec2015-02-03 11:58:06 +0100221
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100222 Mutex log_lock_ ACQUIRED_AFTER(Locks::intern_table_lock_);
223 std::map<mirror::Object*, ObjectLog> object_logs_ GUARDED_BY(log_lock_);
224 std::map<mirror::Array*, ArrayLog> array_logs_ GUARDED_BY(log_lock_);
225 std::list<InternStringLog> intern_string_logs_ GUARDED_BY(log_lock_);
Sebastien Hertz1c80bec2015-02-03 11:58:06 +0100226 bool aborted_ GUARDED_BY(log_lock_);
227 std::string abort_message_ GUARDED_BY(log_lock_);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100228
229 DISALLOW_COPY_AND_ASSIGN(Transaction);
230};
231
232} // namespace art
233
234#endif // ART_RUNTIME_TRANSACTION_H_