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