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
31namespace art {
32namespace mirror {
33class Array;
34class Object;
35class String;
36}
37class InternTable;
38
39class 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
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
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    };
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