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 "gc_root.h"
24 #include "object_callbacks.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 Object;
36 class String;
37 }
38 class InternTable;
39 
40 class Transaction FINAL {
41  public:
42   static constexpr const char* kAbortExceptionDescriptor = "dalvik.system.TransactionAbortError";
43   static constexpr const char* kAbortExceptionSignature = "Ldalvik/system/TransactionAbortError;";
44 
45   Transaction();
46   ~Transaction();
47 
48   void Abort(const std::string& abort_message)
49       REQUIRES(!log_lock_)
50       SHARED_REQUIRES(Locks::mutator_lock_);
51   void ThrowAbortError(Thread* self, const std::string* abort_message)
52       REQUIRES(!log_lock_)
53       SHARED_REQUIRES(Locks::mutator_lock_);
54   bool IsAborted() REQUIRES(!log_lock_);
55 
56   // Record object field changes.
57   void RecordWriteFieldBoolean(mirror::Object* obj, MemberOffset field_offset, uint8_t value,
58                                bool is_volatile)
59       REQUIRES(!log_lock_);
60   void RecordWriteFieldByte(mirror::Object* obj, MemberOffset field_offset, int8_t value,
61                                bool is_volatile)
62       REQUIRES(!log_lock_);
63   void RecordWriteFieldChar(mirror::Object* obj, MemberOffset field_offset, uint16_t value,
64                             bool is_volatile)
65       REQUIRES(!log_lock_);
66   void RecordWriteFieldShort(mirror::Object* obj, MemberOffset field_offset, int16_t value,
67                              bool is_volatile)
68       REQUIRES(!log_lock_);
69   void RecordWriteField32(mirror::Object* obj, MemberOffset field_offset, uint32_t value,
70                           bool is_volatile)
71       REQUIRES(!log_lock_);
72   void RecordWriteField64(mirror::Object* obj, MemberOffset field_offset, uint64_t value,
73                           bool is_volatile)
74       REQUIRES(!log_lock_);
75   void RecordWriteFieldReference(mirror::Object* obj, MemberOffset field_offset,
76                                  mirror::Object* value, bool is_volatile)
77       REQUIRES(!log_lock_);
78 
79   // Record array change.
80   void RecordWriteArray(mirror::Array* array, size_t index, uint64_t value)
81       REQUIRES(!log_lock_)
82       SHARED_REQUIRES(Locks::mutator_lock_);
83 
84   // Record intern string table changes.
85   void RecordStrongStringInsertion(mirror::String* s)
86       REQUIRES(Locks::intern_table_lock_)
87       REQUIRES(!log_lock_);
88   void RecordWeakStringInsertion(mirror::String* s)
89       REQUIRES(Locks::intern_table_lock_)
90       REQUIRES(!log_lock_);
91   void RecordStrongStringRemoval(mirror::String* s)
92       REQUIRES(Locks::intern_table_lock_)
93       REQUIRES(!log_lock_);
94   void RecordWeakStringRemoval(mirror::String* s)
95       REQUIRES(Locks::intern_table_lock_)
96       REQUIRES(!log_lock_);
97 
98   // Abort transaction by undoing all recorded changes.
99   void Rollback()
100       SHARED_REQUIRES(Locks::mutator_lock_)
101       REQUIRES(!log_lock_);
102 
103   void VisitRoots(RootVisitor* visitor)
104       REQUIRES(!log_lock_)
105       SHARED_REQUIRES(Locks::mutator_lock_);
106 
107  private:
108   class ObjectLog : public ValueObject {
109    public:
110     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);
114     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 
118     void Undo(mirror::Object* obj) SHARED_REQUIRES(Locks::mutator_lock_);
119     void VisitRoots(RootVisitor* visitor) SHARED_REQUIRES(Locks::mutator_lock_);
120 
Size()121     size_t Size() const {
122       return field_values_.size();
123     }
124 
125    private:
126     enum FieldValueKind {
127       kBoolean,
128       kByte,
129       kChar,
130       kShort,
131       k32Bits,
132       k64Bits,
133       kReference
134     };
135     struct FieldValue : public ValueObject {
136       // TODO use JValue instead ?
137       uint64_t value;
138       FieldValueKind kind;
139       bool is_volatile;
140     };
141 
142     void LogValue(FieldValueKind kind, MemberOffset offset, uint64_t value, bool is_volatile);
143     void UndoFieldWrite(mirror::Object* obj, MemberOffset field_offset,
144                         const FieldValue& field_value) SHARED_REQUIRES(Locks::mutator_lock_);
145 
146     // Maps field's offset to its value.
147     std::map<uint32_t, FieldValue> field_values_;
148   };
149 
150   class ArrayLog : public ValueObject {
151    public:
152     void LogValue(size_t index, uint64_t value);
153 
154     void Undo(mirror::Array* obj) SHARED_REQUIRES(Locks::mutator_lock_);
155 
Size()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,
162                         uint64_t value) SHARED_REQUIRES(Locks::mutator_lock_);
163 
164     // Maps index to value.
165     // TODO use JValue instead ?
166     std::map<size_t, uint64_t> array_values_;
167   };
168 
169   class InternStringLog : public ValueObject {
170    public:
171     enum StringKind {
172       kStrongString,
173       kWeakString
174     };
175     enum StringOp {
176       kInsert,
177       kRemove
178     };
InternStringLog(mirror::String * s,StringKind kind,StringOp op)179     InternStringLog(mirror::String* s, StringKind kind, StringOp op)
180       : str_(s), string_kind_(kind), string_op_(op) {
181       DCHECK(s != nullptr);
182     }
183 
184     void Undo(InternTable* intern_table)
185         SHARED_REQUIRES(Locks::mutator_lock_)
186         REQUIRES(Locks::intern_table_lock_);
187     void VisitRoots(RootVisitor* visitor) SHARED_REQUIRES(Locks::mutator_lock_);
188 
189    private:
190     mirror::String* str_;
191     const StringKind string_kind_;
192     const StringOp string_op_;
193   };
194 
195   void LogInternedString(const InternStringLog& log)
196       REQUIRES(Locks::intern_table_lock_)
197       REQUIRES(!log_lock_);
198 
199   void UndoObjectModifications()
200       REQUIRES(log_lock_)
201       SHARED_REQUIRES(Locks::mutator_lock_);
202   void UndoArrayModifications()
203       REQUIRES(log_lock_)
204       SHARED_REQUIRES(Locks::mutator_lock_);
205   void UndoInternStringTableModifications()
206       REQUIRES(Locks::intern_table_lock_)
207       REQUIRES(log_lock_)
208       SHARED_REQUIRES(Locks::mutator_lock_);
209 
210   void VisitObjectLogs(RootVisitor* visitor)
211       REQUIRES(log_lock_)
212       SHARED_REQUIRES(Locks::mutator_lock_);
213   void VisitArrayLogs(RootVisitor* visitor)
214       REQUIRES(log_lock_)
215       SHARED_REQUIRES(Locks::mutator_lock_);
216   void VisitStringLogs(RootVisitor* visitor)
217       REQUIRES(log_lock_)
218       SHARED_REQUIRES(Locks::mutator_lock_);
219 
220   const std::string& GetAbortMessage() REQUIRES(!log_lock_);
221 
222   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_);
226   bool aborted_ GUARDED_BY(log_lock_);
227   std::string abort_message_ GUARDED_BY(log_lock_);
228 
229   DISALLOW_COPY_AND_ASSIGN(Transaction);
230 };
231 
232 }  // namespace art
233 
234 #endif  // ART_RUNTIME_TRANSACTION_H_
235