1 /*
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"
22 #include "base/value_object.h"
23 #include "dex_file_types.h"
24 #include "gc_root.h"
25 #include "object_callbacks.h"
26 #include "offsets.h"
27 #include "primitive.h"
28 #include "safe_map.h"
29 
30 #include <list>
31 #include <map>
32 
33 namespace art {
34 namespace mirror {
35 class Array;
36 class DexCache;
37 class Object;
38 class String;
39 }
40 class InternTable;
41 
42 class Transaction FINAL {
43  public:
44   static constexpr const char* kAbortExceptionDescriptor = "dalvik.system.TransactionAbortError";
45   static constexpr const char* kAbortExceptionSignature = "Ldalvik/system/TransactionAbortError;";
46 
47   Transaction();
48   ~Transaction();
49 
50   void Abort(const std::string& abort_message)
51       REQUIRES(!log_lock_)
52       REQUIRES_SHARED(Locks::mutator_lock_);
53   void ThrowAbortError(Thread* self, const std::string* abort_message)
54       REQUIRES(!log_lock_)
55       REQUIRES_SHARED(Locks::mutator_lock_);
56   bool IsAborted() REQUIRES(!log_lock_);
57 
58   // Record object field changes.
59   void RecordWriteFieldBoolean(mirror::Object* obj,
60                                MemberOffset field_offset,
61                                uint8_t value,
62                                bool is_volatile)
63       REQUIRES(!log_lock_);
64   void RecordWriteFieldByte(mirror::Object* obj,
65                             MemberOffset field_offset,
66                             int8_t value,
67                             bool is_volatile)
68       REQUIRES(!log_lock_);
69   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,
77                              bool is_volatile)
78       REQUIRES(!log_lock_);
79   void RecordWriteField32(mirror::Object* obj,
80                           MemberOffset field_offset,
81                           uint32_t value,
82                           bool is_volatile)
83       REQUIRES(!log_lock_);
84   void RecordWriteField64(mirror::Object* obj,
85                           MemberOffset field_offset,
86                           uint64_t value,
87                           bool is_volatile)
88       REQUIRES(!log_lock_);
89   void RecordWriteFieldReference(mirror::Object* obj,
90                                  MemberOffset field_offset,
91                                  mirror::Object* value,
92                                  bool is_volatile)
93       REQUIRES(!log_lock_);
94 
95   // Record array change.
96   void RecordWriteArray(mirror::Array* array, size_t index, uint64_t value)
97       REQUIRES(!log_lock_)
98       REQUIRES_SHARED(Locks::mutator_lock_);
99 
100   // Record intern string table changes.
101   void RecordStrongStringInsertion(ObjPtr<mirror::String> s)
102       REQUIRES(Locks::intern_table_lock_)
103       REQUIRES(!log_lock_);
104   void RecordWeakStringInsertion(ObjPtr<mirror::String> s)
105       REQUIRES(Locks::intern_table_lock_)
106       REQUIRES(!log_lock_);
107   void RecordStrongStringRemoval(ObjPtr<mirror::String> s)
108       REQUIRES(Locks::intern_table_lock_)
109       REQUIRES(!log_lock_);
110   void RecordWeakStringRemoval(ObjPtr<mirror::String> s)
111       REQUIRES(Locks::intern_table_lock_)
112       REQUIRES(!log_lock_);
113 
114   // Record resolve string.
115   void RecordResolveString(ObjPtr<mirror::DexCache> dex_cache, dex::StringIndex string_idx)
116       REQUIRES_SHARED(Locks::mutator_lock_)
117       REQUIRES(!log_lock_);
118 
119   // Abort transaction by undoing all recorded changes.
120   void Rollback()
121       REQUIRES_SHARED(Locks::mutator_lock_)
122       REQUIRES(!log_lock_);
123 
124   void VisitRoots(RootVisitor* visitor)
125       REQUIRES(!log_lock_)
126       REQUIRES_SHARED(Locks::mutator_lock_);
127 
128  private:
129   class ObjectLog : public ValueObject {
130    public:
131     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);
135     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 
139     void Undo(mirror::Object* obj) const REQUIRES_SHARED(Locks::mutator_lock_);
140     void VisitRoots(RootVisitor* visitor) REQUIRES_SHARED(Locks::mutator_lock_);
141 
Size()142     size_t Size() const {
143       return field_values_.size();
144     }
145 
146     ObjectLog() = default;
147     ObjectLog(ObjectLog&& log) = default;
148 
149    private:
150     enum FieldValueKind {
151       kBoolean,
152       kByte,
153       kChar,
154       kShort,
155       k32Bits,
156       k64Bits,
157       kReference
158     };
159     struct FieldValue : public ValueObject {
160       // TODO use JValue instead ?
161       uint64_t value;
162       FieldValueKind kind;
163       bool is_volatile;
164 
FieldValueFieldValue165       FieldValue() : value(0), kind(FieldValueKind::kBoolean), is_volatile(false) {}
166       FieldValue(FieldValue&& log) = default;
167 
168      private:
169       DISALLOW_COPY_AND_ASSIGN(FieldValue);
170     };
171 
172     void LogValue(FieldValueKind kind, MemberOffset offset, uint64_t value, bool is_volatile);
173     void UndoFieldWrite(mirror::Object* obj,
174                         MemberOffset field_offset,
175                         const FieldValue& field_value) const REQUIRES_SHARED(Locks::mutator_lock_);
176 
177     // Maps field's offset to its value.
178     std::map<uint32_t, FieldValue> field_values_;
179 
180     DISALLOW_COPY_AND_ASSIGN(ObjectLog);
181   };
182 
183   class ArrayLog : public ValueObject {
184    public:
185     void LogValue(size_t index, uint64_t value);
186 
187     void Undo(mirror::Array* obj) const REQUIRES_SHARED(Locks::mutator_lock_);
188 
Size()189     size_t Size() const {
190       return array_values_.size();
191     }
192 
193     ArrayLog() = default;
194     ArrayLog(ArrayLog&& log) = default;
195 
196    private:
197     void UndoArrayWrite(mirror::Array* array,
198                         Primitive::Type array_type,
199                         size_t index,
200                         uint64_t value) const REQUIRES_SHARED(Locks::mutator_lock_);
201 
202     // Maps index to value.
203     // TODO use JValue instead ?
204     std::map<size_t, uint64_t> array_values_;
205 
206     DISALLOW_COPY_AND_ASSIGN(ArrayLog);
207   };
208 
209   class InternStringLog : public ValueObject {
210    public:
211     enum StringKind {
212       kStrongString,
213       kWeakString
214     };
215     enum StringOp {
216       kInsert,
217       kRemove
218     };
219     InternStringLog(ObjPtr<mirror::String> s, StringKind kind, StringOp op);
220 
221     void Undo(InternTable* intern_table) const
222         REQUIRES_SHARED(Locks::mutator_lock_)
223         REQUIRES(Locks::intern_table_lock_);
224     void VisitRoots(RootVisitor* visitor) REQUIRES_SHARED(Locks::mutator_lock_);
225 
226     InternStringLog() = default;
227     InternStringLog(InternStringLog&& log) = default;
228 
229    private:
230     mutable GcRoot<mirror::String> str_;
231     const StringKind string_kind_;
232     const StringOp string_op_;
233 
234     DISALLOW_COPY_AND_ASSIGN(InternStringLog);
235   };
236 
237   class ResolveStringLog : public ValueObject {
238    public:
239     ResolveStringLog(ObjPtr<mirror::DexCache> dex_cache, dex::StringIndex string_idx);
240 
241     void Undo() const REQUIRES_SHARED(Locks::mutator_lock_);
242 
243     void VisitRoots(RootVisitor* visitor) REQUIRES_SHARED(Locks::mutator_lock_);
244 
245    private:
246     GcRoot<mirror::DexCache> dex_cache_;
247     const dex::StringIndex string_idx_;
248 
249     DISALLOW_COPY_AND_ASSIGN(ResolveStringLog);
250   };
251 
252   void LogInternedString(InternStringLog&& log)
253       REQUIRES(Locks::intern_table_lock_)
254       REQUIRES(!log_lock_);
255 
256   void UndoObjectModifications()
257       REQUIRES(log_lock_)
258       REQUIRES_SHARED(Locks::mutator_lock_);
259   void UndoArrayModifications()
260       REQUIRES(log_lock_)
261       REQUIRES_SHARED(Locks::mutator_lock_);
262   void UndoInternStringTableModifications()
263       REQUIRES(Locks::intern_table_lock_)
264       REQUIRES(log_lock_)
265       REQUIRES_SHARED(Locks::mutator_lock_);
266   void UndoResolveStringModifications()
267       REQUIRES(log_lock_)
268       REQUIRES_SHARED(Locks::mutator_lock_);
269 
270   void VisitObjectLogs(RootVisitor* visitor)
271       REQUIRES(log_lock_)
272       REQUIRES_SHARED(Locks::mutator_lock_);
273   void VisitArrayLogs(RootVisitor* visitor)
274       REQUIRES(log_lock_)
275       REQUIRES_SHARED(Locks::mutator_lock_);
276   void VisitInternStringLogs(RootVisitor* visitor)
277       REQUIRES(log_lock_)
278       REQUIRES_SHARED(Locks::mutator_lock_);
279   void VisitResolveStringLogs(RootVisitor* visitor)
280       REQUIRES(log_lock_)
281       REQUIRES_SHARED(Locks::mutator_lock_);
282 
283   const std::string& GetAbortMessage() REQUIRES(!log_lock_);
284 
285   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_);
289   std::list<ResolveStringLog> resolve_string_logs_ GUARDED_BY(log_lock_);
290   bool aborted_ GUARDED_BY(log_lock_);
291   std::string abort_message_ GUARDED_BY(log_lock_);
292 
293   DISALLOW_COPY_AND_ASSIGN(Transaction);
294 };
295 
296 }  // namespace art
297 
298 #endif  // ART_RUNTIME_TRANSACTION_H_
299