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 "gc_root.h"
23 #include "object_callbacks.h"
24 #include "offsets.h"
25 #include "primitive.h"
26 #include "safe_map.h"
27 
28 #include <list>
29 #include <map>
30 
31 namespace art {
32 namespace mirror {
33 class Array;
34 class Object;
35 class String;
36 }
37 class InternTable;
38 
39 class Transaction {
40  public:
41   Transaction();
42   ~Transaction();
43 
44   // Record object field changes.
45   void RecordWriteField32(mirror::Object* obj, MemberOffset field_offset, uint32_t value,
46                           bool is_volatile)
47       LOCKS_EXCLUDED(log_lock_);
48   void RecordWriteField64(mirror::Object* obj, MemberOffset field_offset, uint64_t value,
49                           bool is_volatile)
50       LOCKS_EXCLUDED(log_lock_);
51   void RecordWriteFieldReference(mirror::Object* obj, MemberOffset field_offset,
52                                  mirror::Object* value, bool is_volatile)
53       LOCKS_EXCLUDED(log_lock_);
54 
55   // Record array change.
56   void RecordWriteArray(mirror::Array* array, size_t index, uint64_t value)
57       LOCKS_EXCLUDED(log_lock_)
58       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
59 
60   // Record intern string table changes.
61   void RecordStrongStringInsertion(mirror::String* s)
62       EXCLUSIVE_LOCKS_REQUIRED(Locks::intern_table_lock_)
63       LOCKS_EXCLUDED(log_lock_);
64   void RecordWeakStringInsertion(mirror::String* s)
65       EXCLUSIVE_LOCKS_REQUIRED(Locks::intern_table_lock_)
66       LOCKS_EXCLUDED(log_lock_);
67   void RecordStrongStringRemoval(mirror::String* s)
68       EXCLUSIVE_LOCKS_REQUIRED(Locks::intern_table_lock_)
69       LOCKS_EXCLUDED(log_lock_);
70   void RecordWeakStringRemoval(mirror::String* s)
71       EXCLUSIVE_LOCKS_REQUIRED(Locks::intern_table_lock_)
72       LOCKS_EXCLUDED(log_lock_);
73 
74   // Abort transaction by undoing all recorded changes.
75   void Abort()
76       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
77       LOCKS_EXCLUDED(log_lock_);
78 
79   void VisitRoots(RootCallback* callback, void* arg)
80       LOCKS_EXCLUDED(log_lock_)
81       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
82 
83  private:
84   class ObjectLog {
85    public:
86     void Log32BitsValue(MemberOffset offset, uint32_t value, bool is_volatile);
87     void Log64BitsValue(MemberOffset offset, uint64_t value, bool is_volatile);
88     void LogReferenceValue(MemberOffset offset, mirror::Object* obj, bool is_volatile);
89 
90     void Undo(mirror::Object* obj) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
91     void VisitRoots(RootCallback* callback, void* arg);
92 
Size()93     size_t Size() const {
94       return field_values_.size();
95     }
96 
97    private:
98     enum FieldValueKind {
99       k32Bits,
100       k64Bits,
101       kReference
102     };
103     struct FieldValue {
104       // TODO use JValue instead ?
105       uint64_t value;
106       FieldValueKind kind;
107       bool is_volatile;
108     };
109 
110     void UndoFieldWrite(mirror::Object* obj, MemberOffset field_offset,
111                         const FieldValue& field_value) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
112 
113     // Maps field's offset to its value.
114     std::map<uint32_t, FieldValue> field_values_;
115   };
116 
117   class ArrayLog {
118    public:
119     void LogValue(size_t index, uint64_t value);
120 
121     void Undo(mirror::Array* obj) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
122 
Size()123     size_t Size() const {
124       return array_values_.size();
125     }
126 
127    private:
128     void UndoArrayWrite(mirror::Array* array, Primitive::Type array_type, size_t index,
129                         uint64_t value) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
130 
131     // Maps index to value.
132     // TODO use JValue instead ?
133     std::map<size_t, uint64_t> array_values_;
134   };
135 
136   class InternStringLog {
137    public:
138     enum StringKind {
139       kStrongString,
140       kWeakString
141     };
142     enum StringOp {
143       kInsert,
144       kRemove
145     };
InternStringLog(mirror::String * s,StringKind kind,StringOp op)146     InternStringLog(mirror::String* s, StringKind kind, StringOp op)
147       : str_(s), string_kind_(kind), string_op_(op) {
148       DCHECK(s != nullptr);
149     }
150 
151     void Undo(InternTable* intern_table)
152         SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
153         EXCLUSIVE_LOCKS_REQUIRED(Locks::intern_table_lock_);
154     void VisitRoots(RootCallback* callback, void* arg);
155 
156    private:
157     mirror::String* str_;
158     StringKind string_kind_;
159     StringOp string_op_;
160   };
161 
162   void LogInternedString(InternStringLog& log)
163       EXCLUSIVE_LOCKS_REQUIRED(Locks::intern_table_lock_)
164       LOCKS_EXCLUDED(log_lock_);
165 
166   void UndoObjectModifications()
167       EXCLUSIVE_LOCKS_REQUIRED(log_lock_)
168       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
169   void UndoArrayModifications()
170       EXCLUSIVE_LOCKS_REQUIRED(log_lock_)
171       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
172   void UndoInternStringTableModifications()
173       EXCLUSIVE_LOCKS_REQUIRED(Locks::intern_table_lock_)
174       EXCLUSIVE_LOCKS_REQUIRED(log_lock_)
175       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
176 
177   void VisitObjectLogs(RootCallback* callback, void* arg)
178       EXCLUSIVE_LOCKS_REQUIRED(log_lock_)
179       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
180   void VisitArrayLogs(RootCallback* callback, void* arg)
181       EXCLUSIVE_LOCKS_REQUIRED(log_lock_)
182       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
183   void VisitStringLogs(RootCallback* callback, void* arg)
184       EXCLUSIVE_LOCKS_REQUIRED(log_lock_)
185       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
186 
187   Mutex log_lock_ ACQUIRED_AFTER(Locks::intern_table_lock_);
188   std::map<mirror::Object*, ObjectLog> object_logs_ GUARDED_BY(log_lock_);
189   std::map<mirror::Array*, ArrayLog> array_logs_  GUARDED_BY(log_lock_);
190   std::list<InternStringLog> intern_string_logs_ GUARDED_BY(log_lock_);
191 
192   DISALLOW_COPY_AND_ASSIGN(Transaction);
193 };
194 
195 }  // namespace art
196 
197 #endif  // ART_RUNTIME_TRANSACTION_H_
198