xref: /aosp_15_r20/art/dex2oat/transaction.h (revision 795d594fd825385562da6b089ea9b2033f3abf5a)
1*795d594fSAndroid Build Coastguard Worker /*
2*795d594fSAndroid Build Coastguard Worker  * Copyright (C) 2014 The Android Open Source Project
3*795d594fSAndroid Build Coastguard Worker  *
4*795d594fSAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*795d594fSAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*795d594fSAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*795d594fSAndroid Build Coastguard Worker  *
8*795d594fSAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*795d594fSAndroid Build Coastguard Worker  *
10*795d594fSAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*795d594fSAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*795d594fSAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*795d594fSAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*795d594fSAndroid Build Coastguard Worker  * limitations under the License.
15*795d594fSAndroid Build Coastguard Worker  */
16*795d594fSAndroid Build Coastguard Worker 
17*795d594fSAndroid Build Coastguard Worker #ifndef ART_DEX2OAT_TRANSACTION_H_
18*795d594fSAndroid Build Coastguard Worker #define ART_DEX2OAT_TRANSACTION_H_
19*795d594fSAndroid Build Coastguard Worker 
20*795d594fSAndroid Build Coastguard Worker #include "base/scoped_arena_containers.h"
21*795d594fSAndroid Build Coastguard Worker #include "base/macros.h"
22*795d594fSAndroid Build Coastguard Worker #include "base/mutex.h"
23*795d594fSAndroid Build Coastguard Worker #include "base/safe_map.h"
24*795d594fSAndroid Build Coastguard Worker #include "base/value_object.h"
25*795d594fSAndroid Build Coastguard Worker #include "dex/dex_file_types.h"
26*795d594fSAndroid Build Coastguard Worker #include "dex/primitive.h"
27*795d594fSAndroid Build Coastguard Worker #include "gc_root.h"
28*795d594fSAndroid Build Coastguard Worker #include "offsets.h"
29*795d594fSAndroid Build Coastguard Worker 
30*795d594fSAndroid Build Coastguard Worker #include <list>
31*795d594fSAndroid Build Coastguard Worker #include <map>
32*795d594fSAndroid Build Coastguard Worker 
33*795d594fSAndroid Build Coastguard Worker namespace art HIDDEN {
34*795d594fSAndroid Build Coastguard Worker namespace gc {
35*795d594fSAndroid Build Coastguard Worker class Heap;
36*795d594fSAndroid Build Coastguard Worker }  // namespace gc
37*795d594fSAndroid Build Coastguard Worker namespace mirror {
38*795d594fSAndroid Build Coastguard Worker class Array;
39*795d594fSAndroid Build Coastguard Worker class Class;
40*795d594fSAndroid Build Coastguard Worker class DexCache;
41*795d594fSAndroid Build Coastguard Worker class Object;
42*795d594fSAndroid Build Coastguard Worker class String;
43*795d594fSAndroid Build Coastguard Worker }  // namespace mirror
44*795d594fSAndroid Build Coastguard Worker class InternTable;
45*795d594fSAndroid Build Coastguard Worker template<class MirrorType> class ObjPtr;
46*795d594fSAndroid Build Coastguard Worker 
47*795d594fSAndroid Build Coastguard Worker class Transaction final {
48*795d594fSAndroid Build Coastguard Worker  public:
49*795d594fSAndroid Build Coastguard Worker   Transaction(bool strict, mirror::Class* root, ArenaStack* arena_stack, ArenaPool* arena_pool);
50*795d594fSAndroid Build Coastguard Worker   ~Transaction();
51*795d594fSAndroid Build Coastguard Worker 
GetArenaStack()52*795d594fSAndroid Build Coastguard Worker   ArenaStack* GetArenaStack() {
53*795d594fSAndroid Build Coastguard Worker     return allocator_.GetArenaStack();
54*795d594fSAndroid Build Coastguard Worker   }
55*795d594fSAndroid Build Coastguard Worker 
56*795d594fSAndroid Build Coastguard Worker   void Abort(const std::string& abort_message)
57*795d594fSAndroid Build Coastguard Worker       REQUIRES_SHARED(Locks::mutator_lock_);
58*795d594fSAndroid Build Coastguard Worker   void ThrowAbortError(Thread* self, const std::string* abort_message)
59*795d594fSAndroid Build Coastguard Worker       REQUIRES_SHARED(Locks::mutator_lock_);
IsAborted()60*795d594fSAndroid Build Coastguard Worker   bool IsAborted() const {
61*795d594fSAndroid Build Coastguard Worker     return aborted_;
62*795d594fSAndroid Build Coastguard Worker   }
63*795d594fSAndroid Build Coastguard Worker 
64*795d594fSAndroid Build Coastguard Worker   // If the transaction is rollbacking. Transactions will set this flag when they start rollbacking,
65*795d594fSAndroid Build Coastguard Worker   // because the nested transaction should be disabled when rollbacking to restore the memory.
IsRollingBack()66*795d594fSAndroid Build Coastguard Worker   bool IsRollingBack() const {
67*795d594fSAndroid Build Coastguard Worker     return rolling_back_;
68*795d594fSAndroid Build Coastguard Worker   }
69*795d594fSAndroid Build Coastguard Worker 
70*795d594fSAndroid Build Coastguard Worker   // If the transaction is in strict mode, then all access of static fields will be constrained,
71*795d594fSAndroid Build Coastguard Worker   // one class's clinit will not be allowed to read or modify another class's static fields, unless
72*795d594fSAndroid Build Coastguard Worker   // the transaction is aborted.
IsStrict()73*795d594fSAndroid Build Coastguard Worker   bool IsStrict() const {
74*795d594fSAndroid Build Coastguard Worker     return strict_;
75*795d594fSAndroid Build Coastguard Worker   }
76*795d594fSAndroid Build Coastguard Worker 
77*795d594fSAndroid Build Coastguard Worker   // Record newly allocated object/array.
78*795d594fSAndroid Build Coastguard Worker   //
79*795d594fSAndroid Build Coastguard Worker   // There is no reason to record old values for newly allocated objects because they become
80*795d594fSAndroid Build Coastguard Worker   // unreachable when the transaction is rolled back, so their data does not need to be rolled back.
81*795d594fSAndroid Build Coastguard Worker   //
82*795d594fSAndroid Build Coastguard Worker   // Implementation details: We track all newly allocated objects/arrays by creating an
83*795d594fSAndroid Build Coastguard Worker   // `ObjectLog`/`ArrayLog` flagged as a new object/array. We also cache the last allocated
84*795d594fSAndroid Build Coastguard Worker   // object/array which often helps avoid the search for the flagged `ObjectLog`/`ArrayLog`.
85*795d594fSAndroid Build Coastguard Worker   void RecordNewObject(ObjPtr<mirror::Object> allocated_object)
86*795d594fSAndroid Build Coastguard Worker       REQUIRES_SHARED(Locks::mutator_lock_);
87*795d594fSAndroid Build Coastguard Worker   void RecordNewArray(ObjPtr<mirror::Array> allocated_object)
88*795d594fSAndroid Build Coastguard Worker       REQUIRES_SHARED(Locks::mutator_lock_);
89*795d594fSAndroid Build Coastguard Worker 
90*795d594fSAndroid Build Coastguard Worker   bool ObjectNeedsTransactionRecords(ObjPtr<mirror::Object> obj)
91*795d594fSAndroid Build Coastguard Worker       REQUIRES_SHARED(Locks::mutator_lock_);
92*795d594fSAndroid Build Coastguard Worker   bool ArrayNeedsTransactionRecords(ObjPtr<mirror::Array> array)
93*795d594fSAndroid Build Coastguard Worker       REQUIRES_SHARED(Locks::mutator_lock_);
94*795d594fSAndroid Build Coastguard Worker 
95*795d594fSAndroid Build Coastguard Worker   // Record object field changes.
96*795d594fSAndroid Build Coastguard Worker   void RecordWriteFieldBoolean(mirror::Object* obj,
97*795d594fSAndroid Build Coastguard Worker                                MemberOffset field_offset,
98*795d594fSAndroid Build Coastguard Worker                                uint8_t value,
99*795d594fSAndroid Build Coastguard Worker                                bool is_volatile);
100*795d594fSAndroid Build Coastguard Worker   void RecordWriteFieldByte(mirror::Object* obj,
101*795d594fSAndroid Build Coastguard Worker                             MemberOffset field_offset,
102*795d594fSAndroid Build Coastguard Worker                             int8_t value,
103*795d594fSAndroid Build Coastguard Worker                             bool is_volatile);
104*795d594fSAndroid Build Coastguard Worker   void RecordWriteFieldChar(mirror::Object* obj,
105*795d594fSAndroid Build Coastguard Worker                             MemberOffset field_offset,
106*795d594fSAndroid Build Coastguard Worker                             uint16_t value,
107*795d594fSAndroid Build Coastguard Worker                             bool is_volatile);
108*795d594fSAndroid Build Coastguard Worker   void RecordWriteFieldShort(mirror::Object* obj,
109*795d594fSAndroid Build Coastguard Worker                              MemberOffset field_offset,
110*795d594fSAndroid Build Coastguard Worker                              int16_t value,
111*795d594fSAndroid Build Coastguard Worker                              bool is_volatile);
112*795d594fSAndroid Build Coastguard Worker   void RecordWriteField32(mirror::Object* obj,
113*795d594fSAndroid Build Coastguard Worker                           MemberOffset field_offset,
114*795d594fSAndroid Build Coastguard Worker                           uint32_t value,
115*795d594fSAndroid Build Coastguard Worker                           bool is_volatile);
116*795d594fSAndroid Build Coastguard Worker   void RecordWriteField64(mirror::Object* obj,
117*795d594fSAndroid Build Coastguard Worker                           MemberOffset field_offset,
118*795d594fSAndroid Build Coastguard Worker                           uint64_t value,
119*795d594fSAndroid Build Coastguard Worker                           bool is_volatile);
120*795d594fSAndroid Build Coastguard Worker   void RecordWriteFieldReference(mirror::Object* obj,
121*795d594fSAndroid Build Coastguard Worker                                  MemberOffset field_offset,
122*795d594fSAndroid Build Coastguard Worker                                  mirror::Object* value,
123*795d594fSAndroid Build Coastguard Worker                                  bool is_volatile);
124*795d594fSAndroid Build Coastguard Worker 
125*795d594fSAndroid Build Coastguard Worker   // Record array change.
126*795d594fSAndroid Build Coastguard Worker   void RecordWriteArray(mirror::Array* array, size_t index, uint64_t value)
127*795d594fSAndroid Build Coastguard Worker       REQUIRES_SHARED(Locks::mutator_lock_);
128*795d594fSAndroid Build Coastguard Worker 
129*795d594fSAndroid Build Coastguard Worker   // Record intern string table changes.
130*795d594fSAndroid Build Coastguard Worker   void RecordStrongStringInsertion(ObjPtr<mirror::String> s)
131*795d594fSAndroid Build Coastguard Worker       REQUIRES(Locks::intern_table_lock_);
132*795d594fSAndroid Build Coastguard Worker   void RecordWeakStringInsertion(ObjPtr<mirror::String> s)
133*795d594fSAndroid Build Coastguard Worker       REQUIRES(Locks::intern_table_lock_);
134*795d594fSAndroid Build Coastguard Worker   void RecordStrongStringRemoval(ObjPtr<mirror::String> s)
135*795d594fSAndroid Build Coastguard Worker       REQUIRES(Locks::intern_table_lock_);
136*795d594fSAndroid Build Coastguard Worker   void RecordWeakStringRemoval(ObjPtr<mirror::String> s)
137*795d594fSAndroid Build Coastguard Worker       REQUIRES(Locks::intern_table_lock_);
138*795d594fSAndroid Build Coastguard Worker 
139*795d594fSAndroid Build Coastguard Worker   // Record resolve string.
140*795d594fSAndroid Build Coastguard Worker   void RecordResolveString(ObjPtr<mirror::DexCache> dex_cache, dex::StringIndex string_idx)
141*795d594fSAndroid Build Coastguard Worker       REQUIRES_SHARED(Locks::mutator_lock_);
142*795d594fSAndroid Build Coastguard Worker 
143*795d594fSAndroid Build Coastguard Worker   // Record resolve method type.
144*795d594fSAndroid Build Coastguard Worker   void RecordResolveMethodType(ObjPtr<mirror::DexCache> dex_cache, dex::ProtoIndex proto_idx)
145*795d594fSAndroid Build Coastguard Worker       REQUIRES_SHARED(Locks::mutator_lock_);
146*795d594fSAndroid Build Coastguard Worker 
147*795d594fSAndroid Build Coastguard Worker   // Abort transaction by undoing all recorded changes.
148*795d594fSAndroid Build Coastguard Worker   void Rollback()
149*795d594fSAndroid Build Coastguard Worker       REQUIRES_SHARED(Locks::mutator_lock_);
150*795d594fSAndroid Build Coastguard Worker 
151*795d594fSAndroid Build Coastguard Worker   void VisitRoots(RootVisitor* visitor)
152*795d594fSAndroid Build Coastguard Worker       REQUIRES_SHARED(Locks::mutator_lock_);
153*795d594fSAndroid Build Coastguard Worker 
154*795d594fSAndroid Build Coastguard Worker   bool ReadConstraint(ObjPtr<mirror::Object> obj) const
155*795d594fSAndroid Build Coastguard Worker       REQUIRES_SHARED(Locks::mutator_lock_);
156*795d594fSAndroid Build Coastguard Worker 
157*795d594fSAndroid Build Coastguard Worker   bool WriteConstraint(ObjPtr<mirror::Object> obj) const
158*795d594fSAndroid Build Coastguard Worker       REQUIRES_SHARED(Locks::mutator_lock_);
159*795d594fSAndroid Build Coastguard Worker 
160*795d594fSAndroid Build Coastguard Worker   bool WriteValueConstraint(ObjPtr<mirror::Object> value) const
161*795d594fSAndroid Build Coastguard Worker       REQUIRES_SHARED(Locks::mutator_lock_);
162*795d594fSAndroid Build Coastguard Worker 
163*795d594fSAndroid Build Coastguard Worker  private:
164*795d594fSAndroid Build Coastguard Worker   class ObjectLog : public ValueObject {
165*795d594fSAndroid Build Coastguard Worker    public:
166*795d594fSAndroid Build Coastguard Worker     void LogBooleanValue(MemberOffset offset, uint8_t value, bool is_volatile);
167*795d594fSAndroid Build Coastguard Worker     void LogByteValue(MemberOffset offset, int8_t value, bool is_volatile);
168*795d594fSAndroid Build Coastguard Worker     void LogCharValue(MemberOffset offset, uint16_t value, bool is_volatile);
169*795d594fSAndroid Build Coastguard Worker     void LogShortValue(MemberOffset offset, int16_t value, bool is_volatile);
170*795d594fSAndroid Build Coastguard Worker     void Log32BitsValue(MemberOffset offset, uint32_t value, bool is_volatile);
171*795d594fSAndroid Build Coastguard Worker     void Log64BitsValue(MemberOffset offset, uint64_t value, bool is_volatile);
172*795d594fSAndroid Build Coastguard Worker     void LogReferenceValue(MemberOffset offset, mirror::Object* obj, bool is_volatile);
173*795d594fSAndroid Build Coastguard Worker 
174*795d594fSAndroid Build Coastguard Worker     void Undo(mirror::Object* obj) const REQUIRES_SHARED(Locks::mutator_lock_);
175*795d594fSAndroid Build Coastguard Worker     void VisitRoots(RootVisitor* visitor) REQUIRES_SHARED(Locks::mutator_lock_);
176*795d594fSAndroid Build Coastguard Worker 
Size()177*795d594fSAndroid Build Coastguard Worker     size_t Size() const {
178*795d594fSAndroid Build Coastguard Worker       return field_values_.size();
179*795d594fSAndroid Build Coastguard Worker     }
180*795d594fSAndroid Build Coastguard Worker 
MarkAsNewObject()181*795d594fSAndroid Build Coastguard Worker     void MarkAsNewObject() {
182*795d594fSAndroid Build Coastguard Worker       DCHECK(field_values_.empty());
183*795d594fSAndroid Build Coastguard Worker       is_new_object_ = true;
184*795d594fSAndroid Build Coastguard Worker     }
185*795d594fSAndroid Build Coastguard Worker 
IsNewObject()186*795d594fSAndroid Build Coastguard Worker     bool IsNewObject() const {
187*795d594fSAndroid Build Coastguard Worker       return is_new_object_;
188*795d594fSAndroid Build Coastguard Worker     }
189*795d594fSAndroid Build Coastguard Worker 
ObjectLog(ScopedArenaAllocator * allocator)190*795d594fSAndroid Build Coastguard Worker     explicit ObjectLog(ScopedArenaAllocator* allocator)
191*795d594fSAndroid Build Coastguard Worker         : is_new_object_(false),
192*795d594fSAndroid Build Coastguard Worker           field_values_(std::less<uint32_t>(), allocator->Adapter(kArenaAllocTransaction)) {}
193*795d594fSAndroid Build Coastguard Worker     ObjectLog(ObjectLog&& log) = default;
194*795d594fSAndroid Build Coastguard Worker 
195*795d594fSAndroid Build Coastguard Worker    private:
196*795d594fSAndroid Build Coastguard Worker     enum FieldValueKind {
197*795d594fSAndroid Build Coastguard Worker       kBoolean,
198*795d594fSAndroid Build Coastguard Worker       kByte,
199*795d594fSAndroid Build Coastguard Worker       kChar,
200*795d594fSAndroid Build Coastguard Worker       kShort,
201*795d594fSAndroid Build Coastguard Worker       k32Bits,
202*795d594fSAndroid Build Coastguard Worker       k64Bits,
203*795d594fSAndroid Build Coastguard Worker       kReference
204*795d594fSAndroid Build Coastguard Worker     };
205*795d594fSAndroid Build Coastguard Worker     struct FieldValue : public ValueObject {
206*795d594fSAndroid Build Coastguard Worker       // TODO use JValue instead ?
207*795d594fSAndroid Build Coastguard Worker       uint64_t value;
208*795d594fSAndroid Build Coastguard Worker       FieldValueKind kind;
209*795d594fSAndroid Build Coastguard Worker       bool is_volatile;
210*795d594fSAndroid Build Coastguard Worker 
FieldValueFieldValue211*795d594fSAndroid Build Coastguard Worker       FieldValue() : value(0), kind(FieldValueKind::kBoolean), is_volatile(false) {}
212*795d594fSAndroid Build Coastguard Worker       FieldValue(FieldValue&& log) = default;
213*795d594fSAndroid Build Coastguard Worker 
214*795d594fSAndroid Build Coastguard Worker      private:
215*795d594fSAndroid Build Coastguard Worker       DISALLOW_COPY_AND_ASSIGN(FieldValue);
216*795d594fSAndroid Build Coastguard Worker     };
217*795d594fSAndroid Build Coastguard Worker 
218*795d594fSAndroid Build Coastguard Worker     void LogValue(FieldValueKind kind, MemberOffset offset, uint64_t value, bool is_volatile);
219*795d594fSAndroid Build Coastguard Worker     void UndoFieldWrite(mirror::Object* obj,
220*795d594fSAndroid Build Coastguard Worker                         MemberOffset field_offset,
221*795d594fSAndroid Build Coastguard Worker                         const FieldValue& field_value) const REQUIRES_SHARED(Locks::mutator_lock_);
222*795d594fSAndroid Build Coastguard Worker 
223*795d594fSAndroid Build Coastguard Worker     // Whether this is a new object. We do not need to keep transaction records for objects
224*795d594fSAndroid Build Coastguard Worker     // created inside a transaction because they become unreachable on rollback.
225*795d594fSAndroid Build Coastguard Worker     bool is_new_object_;
226*795d594fSAndroid Build Coastguard Worker 
227*795d594fSAndroid Build Coastguard Worker     // Maps field's offset to its value.
228*795d594fSAndroid Build Coastguard Worker     ScopedArenaSafeMap<uint32_t, FieldValue> field_values_;
229*795d594fSAndroid Build Coastguard Worker 
230*795d594fSAndroid Build Coastguard Worker     DISALLOW_COPY_AND_ASSIGN(ObjectLog);
231*795d594fSAndroid Build Coastguard Worker   };
232*795d594fSAndroid Build Coastguard Worker 
233*795d594fSAndroid Build Coastguard Worker   class ArrayLog : public ValueObject {
234*795d594fSAndroid Build Coastguard Worker    public:
235*795d594fSAndroid Build Coastguard Worker     void LogValue(size_t index, uint64_t value);
236*795d594fSAndroid Build Coastguard Worker 
237*795d594fSAndroid Build Coastguard Worker     void Undo(mirror::Array* obj) const REQUIRES_SHARED(Locks::mutator_lock_);
238*795d594fSAndroid Build Coastguard Worker 
Size()239*795d594fSAndroid Build Coastguard Worker     size_t Size() const {
240*795d594fSAndroid Build Coastguard Worker       return array_values_.size();
241*795d594fSAndroid Build Coastguard Worker     }
242*795d594fSAndroid Build Coastguard Worker 
MarkAsNewArray()243*795d594fSAndroid Build Coastguard Worker     void MarkAsNewArray() {
244*795d594fSAndroid Build Coastguard Worker       DCHECK(array_values_.empty());
245*795d594fSAndroid Build Coastguard Worker       is_new_array_ = true;
246*795d594fSAndroid Build Coastguard Worker     }
247*795d594fSAndroid Build Coastguard Worker 
IsNewArray()248*795d594fSAndroid Build Coastguard Worker     bool IsNewArray() const {
249*795d594fSAndroid Build Coastguard Worker       return is_new_array_;
250*795d594fSAndroid Build Coastguard Worker     }
251*795d594fSAndroid Build Coastguard Worker 
ArrayLog(ScopedArenaAllocator * allocator)252*795d594fSAndroid Build Coastguard Worker     explicit ArrayLog(ScopedArenaAllocator* allocator)
253*795d594fSAndroid Build Coastguard Worker         : is_new_array_(false),
254*795d594fSAndroid Build Coastguard Worker           array_values_(std::less<size_t>(), allocator->Adapter(kArenaAllocTransaction)) {}
255*795d594fSAndroid Build Coastguard Worker 
256*795d594fSAndroid Build Coastguard Worker     ArrayLog(ArrayLog&& log) = default;
257*795d594fSAndroid Build Coastguard Worker 
258*795d594fSAndroid Build Coastguard Worker    private:
259*795d594fSAndroid Build Coastguard Worker     void UndoArrayWrite(mirror::Array* array,
260*795d594fSAndroid Build Coastguard Worker                         Primitive::Type array_type,
261*795d594fSAndroid Build Coastguard Worker                         size_t index,
262*795d594fSAndroid Build Coastguard Worker                         uint64_t value) const REQUIRES_SHARED(Locks::mutator_lock_);
263*795d594fSAndroid Build Coastguard Worker 
264*795d594fSAndroid Build Coastguard Worker     // Whether this is a new array. We do not need to keep transaction records for arrays
265*795d594fSAndroid Build Coastguard Worker     // created inside a transaction because they become unreachable on rollback.
266*795d594fSAndroid Build Coastguard Worker     bool is_new_array_;
267*795d594fSAndroid Build Coastguard Worker 
268*795d594fSAndroid Build Coastguard Worker     // Maps index to value.
269*795d594fSAndroid Build Coastguard Worker     // TODO use JValue instead ?
270*795d594fSAndroid Build Coastguard Worker     ScopedArenaSafeMap<size_t, uint64_t> array_values_;
271*795d594fSAndroid Build Coastguard Worker 
272*795d594fSAndroid Build Coastguard Worker     DISALLOW_COPY_AND_ASSIGN(ArrayLog);
273*795d594fSAndroid Build Coastguard Worker   };
274*795d594fSAndroid Build Coastguard Worker 
275*795d594fSAndroid Build Coastguard Worker   class InternStringLog : public ValueObject {
276*795d594fSAndroid Build Coastguard Worker    public:
277*795d594fSAndroid Build Coastguard Worker     enum StringKind {
278*795d594fSAndroid Build Coastguard Worker       kStrongString,
279*795d594fSAndroid Build Coastguard Worker       kWeakString
280*795d594fSAndroid Build Coastguard Worker     };
281*795d594fSAndroid Build Coastguard Worker     enum StringOp {
282*795d594fSAndroid Build Coastguard Worker       kInsert,
283*795d594fSAndroid Build Coastguard Worker       kRemove
284*795d594fSAndroid Build Coastguard Worker     };
285*795d594fSAndroid Build Coastguard Worker     InternStringLog(ObjPtr<mirror::String> s, StringKind kind, StringOp op);
286*795d594fSAndroid Build Coastguard Worker 
287*795d594fSAndroid Build Coastguard Worker     void Undo(InternTable* intern_table) const
288*795d594fSAndroid Build Coastguard Worker         REQUIRES_SHARED(Locks::mutator_lock_)
289*795d594fSAndroid Build Coastguard Worker         REQUIRES(Locks::intern_table_lock_);
290*795d594fSAndroid Build Coastguard Worker     void VisitRoots(RootVisitor* visitor) REQUIRES_SHARED(Locks::mutator_lock_);
291*795d594fSAndroid Build Coastguard Worker 
292*795d594fSAndroid Build Coastguard Worker     // Only the move constructor is supported.
293*795d594fSAndroid Build Coastguard Worker     InternStringLog() = delete;
294*795d594fSAndroid Build Coastguard Worker     InternStringLog(const InternStringLog& log) = delete;
295*795d594fSAndroid Build Coastguard Worker     InternStringLog& operator=(const InternStringLog& log) = delete;
296*795d594fSAndroid Build Coastguard Worker     InternStringLog(InternStringLog&& log) = default;
297*795d594fSAndroid Build Coastguard Worker     InternStringLog& operator=(InternStringLog&& log) = delete;
298*795d594fSAndroid Build Coastguard Worker 
299*795d594fSAndroid Build Coastguard Worker    private:
300*795d594fSAndroid Build Coastguard Worker     mutable GcRoot<mirror::String> str_;
301*795d594fSAndroid Build Coastguard Worker     const StringKind string_kind_;
302*795d594fSAndroid Build Coastguard Worker     const StringOp string_op_;
303*795d594fSAndroid Build Coastguard Worker   };
304*795d594fSAndroid Build Coastguard Worker 
305*795d594fSAndroid Build Coastguard Worker   class ResolveStringLog : public ValueObject {
306*795d594fSAndroid Build Coastguard Worker    public:
307*795d594fSAndroid Build Coastguard Worker     ResolveStringLog(ObjPtr<mirror::DexCache> dex_cache, dex::StringIndex string_idx);
308*795d594fSAndroid Build Coastguard Worker 
309*795d594fSAndroid Build Coastguard Worker     void Undo() const REQUIRES_SHARED(Locks::mutator_lock_);
310*795d594fSAndroid Build Coastguard Worker 
311*795d594fSAndroid Build Coastguard Worker     void VisitRoots(RootVisitor* visitor) REQUIRES_SHARED(Locks::mutator_lock_);
312*795d594fSAndroid Build Coastguard Worker 
313*795d594fSAndroid Build Coastguard Worker    private:
314*795d594fSAndroid Build Coastguard Worker     GcRoot<mirror::DexCache> dex_cache_;
315*795d594fSAndroid Build Coastguard Worker     const dex::StringIndex string_idx_;
316*795d594fSAndroid Build Coastguard Worker 
317*795d594fSAndroid Build Coastguard Worker     DISALLOW_COPY_AND_ASSIGN(ResolveStringLog);
318*795d594fSAndroid Build Coastguard Worker   };
319*795d594fSAndroid Build Coastguard Worker 
320*795d594fSAndroid Build Coastguard Worker   class ResolveMethodTypeLog : public ValueObject {
321*795d594fSAndroid Build Coastguard Worker    public:
322*795d594fSAndroid Build Coastguard Worker     ResolveMethodTypeLog(ObjPtr<mirror::DexCache> dex_cache, dex::ProtoIndex proto_idx);
323*795d594fSAndroid Build Coastguard Worker 
324*795d594fSAndroid Build Coastguard Worker     void Undo() const REQUIRES_SHARED(Locks::mutator_lock_);
325*795d594fSAndroid Build Coastguard Worker 
326*795d594fSAndroid Build Coastguard Worker     void VisitRoots(RootVisitor* visitor) REQUIRES_SHARED(Locks::mutator_lock_);
327*795d594fSAndroid Build Coastguard Worker 
328*795d594fSAndroid Build Coastguard Worker    private:
329*795d594fSAndroid Build Coastguard Worker     GcRoot<mirror::DexCache> dex_cache_;
330*795d594fSAndroid Build Coastguard Worker     const dex::ProtoIndex proto_idx_;
331*795d594fSAndroid Build Coastguard Worker 
332*795d594fSAndroid Build Coastguard Worker     DISALLOW_COPY_AND_ASSIGN(ResolveMethodTypeLog);
333*795d594fSAndroid Build Coastguard Worker   };
334*795d594fSAndroid Build Coastguard Worker 
335*795d594fSAndroid Build Coastguard Worker   void LogInternedString(InternStringLog&& log)
336*795d594fSAndroid Build Coastguard Worker       REQUIRES(Locks::intern_table_lock_);
337*795d594fSAndroid Build Coastguard Worker 
338*795d594fSAndroid Build Coastguard Worker   void UndoObjectModifications()
339*795d594fSAndroid Build Coastguard Worker       REQUIRES_SHARED(Locks::mutator_lock_);
340*795d594fSAndroid Build Coastguard Worker   void UndoArrayModifications()
341*795d594fSAndroid Build Coastguard Worker       REQUIRES_SHARED(Locks::mutator_lock_);
342*795d594fSAndroid Build Coastguard Worker   void UndoInternStringTableModifications()
343*795d594fSAndroid Build Coastguard Worker       REQUIRES(Locks::intern_table_lock_)
344*795d594fSAndroid Build Coastguard Worker       REQUIRES_SHARED(Locks::mutator_lock_);
345*795d594fSAndroid Build Coastguard Worker   void UndoResolveStringModifications()
346*795d594fSAndroid Build Coastguard Worker       REQUIRES_SHARED(Locks::mutator_lock_);
347*795d594fSAndroid Build Coastguard Worker   void UndoResolveMethodTypeModifications()
348*795d594fSAndroid Build Coastguard Worker       REQUIRES_SHARED(Locks::mutator_lock_);
349*795d594fSAndroid Build Coastguard Worker 
350*795d594fSAndroid Build Coastguard Worker   void VisitObjectLogs(RootVisitor* visitor, ArenaStack* arena_stack)
351*795d594fSAndroid Build Coastguard Worker       REQUIRES_SHARED(Locks::mutator_lock_);
352*795d594fSAndroid Build Coastguard Worker   void VisitArrayLogs(RootVisitor* visitor, ArenaStack* arena_stack)
353*795d594fSAndroid Build Coastguard Worker       REQUIRES_SHARED(Locks::mutator_lock_);
354*795d594fSAndroid Build Coastguard Worker   void VisitInternStringLogs(RootVisitor* visitor)
355*795d594fSAndroid Build Coastguard Worker       REQUIRES_SHARED(Locks::mutator_lock_);
356*795d594fSAndroid Build Coastguard Worker   void VisitResolveStringLogs(RootVisitor* visitor)
357*795d594fSAndroid Build Coastguard Worker       REQUIRES_SHARED(Locks::mutator_lock_);
358*795d594fSAndroid Build Coastguard Worker   void VisitResolveMethodTypeLogs(RootVisitor* visitor)
359*795d594fSAndroid Build Coastguard Worker       REQUIRES_SHARED(Locks::mutator_lock_);
360*795d594fSAndroid Build Coastguard Worker 
361*795d594fSAndroid Build Coastguard Worker   const std::string& GetAbortMessage() const;
362*795d594fSAndroid Build Coastguard Worker 
363*795d594fSAndroid Build Coastguard Worker   ObjectLog& GetOrCreateObjectLog(mirror::Object* obj);
364*795d594fSAndroid Build Coastguard Worker 
365*795d594fSAndroid Build Coastguard Worker   // The top-level transaction creates an `ArenaStack` which is then
366*795d594fSAndroid Build Coastguard Worker   // passed down to nested transactions.
367*795d594fSAndroid Build Coastguard Worker   std::optional<ArenaStack> arena_stack_;
368*795d594fSAndroid Build Coastguard Worker   // The allocator uses the `ArenaStack` from the top-level transaction.
369*795d594fSAndroid Build Coastguard Worker   ScopedArenaAllocator allocator_;
370*795d594fSAndroid Build Coastguard Worker 
371*795d594fSAndroid Build Coastguard Worker   ScopedArenaSafeMap<mirror::Object*, ObjectLog> object_logs_;
372*795d594fSAndroid Build Coastguard Worker   ScopedArenaSafeMap<mirror::Array*, ArrayLog> array_logs_;
373*795d594fSAndroid Build Coastguard Worker   ScopedArenaForwardList<InternStringLog> intern_string_logs_;
374*795d594fSAndroid Build Coastguard Worker   ScopedArenaForwardList<ResolveStringLog> resolve_string_logs_;
375*795d594fSAndroid Build Coastguard Worker   ScopedArenaForwardList<ResolveMethodTypeLog> resolve_method_type_logs_;
376*795d594fSAndroid Build Coastguard Worker   bool aborted_;
377*795d594fSAndroid Build Coastguard Worker   bool rolling_back_;  // Single thread, no race.
378*795d594fSAndroid Build Coastguard Worker   gc::Heap* const heap_;
379*795d594fSAndroid Build Coastguard Worker   const bool strict_;
380*795d594fSAndroid Build Coastguard Worker   std::string abort_message_;
381*795d594fSAndroid Build Coastguard Worker   mirror::Class* root_;
382*795d594fSAndroid Build Coastguard Worker   mirror::Object* last_allocated_object_;
383*795d594fSAndroid Build Coastguard Worker 
384*795d594fSAndroid Build Coastguard Worker   DISALLOW_COPY_AND_ASSIGN(Transaction);
385*795d594fSAndroid Build Coastguard Worker };
386*795d594fSAndroid Build Coastguard Worker 
387*795d594fSAndroid Build Coastguard Worker }  // namespace art
388*795d594fSAndroid Build Coastguard Worker 
389*795d594fSAndroid Build Coastguard Worker #endif  // ART_DEX2OAT_TRANSACTION_H_
390