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