blob: d1470388f3345e759c0c006f9cb9f6e4640151be [file] [log] [blame]
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +01001/*
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
Vladimir Markob6e67922021-07-06 15:53:07 +010020#include "base/scoped_arena_containers.h"
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +010021#include "base/macros.h"
22#include "base/mutex.h"
David Sehr67bf42e2018-02-26 16:43:04 -080023#include "base/safe_map.h"
Ian Rogers6a3c1fc2014-10-31 00:33:20 -070024#include "base/value_object.h"
David Sehr9e734c72018-01-04 17:56:19 -080025#include "dex/dex_file_types.h"
David Sehr67bf42e2018-02-26 16:43:04 -080026#include "dex/primitive.h"
Mathieu Chartiere34fa1d2015-01-14 14:55:47 -080027#include "gc_root.h"
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +010028#include "offsets.h"
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +010029
30#include <list>
31#include <map>
32
33namespace art {
Vladimir Marko672c0802019-07-26 13:03:13 +010034namespace gc {
35class Heap;
36} // namespace gc
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +010037namespace mirror {
38class Array;
Chang Xingcade5c32017-07-20 17:56:26 -070039class Class;
Mathieu Chartierbb816d62016-09-07 10:17:46 -070040class DexCache;
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +010041class Object;
42class String;
Andreas Gampedeae7db2017-05-30 09:56:41 -070043} // namespace mirror
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +010044class InternTable;
Vladimir Marko672c0802019-07-26 13:03:13 +010045template<class MirrorType> class ObjPtr;
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +010046
Roland Levillainbbc6e7e2018-08-24 16:58:47 +010047class Transaction final {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +010048 public:
Vladimir Marko0685b982021-03-25 11:59:22 +000049 static constexpr const char* kAbortExceptionDescriptor = "Ldalvik/system/TransactionAbortError;";
Sebastien Hertz2fd7e692015-04-02 11:11:19 +020050
Vladimir Markob6e67922021-07-06 15:53:07 +010051 Transaction(bool strict, mirror::Class* root, ArenaStack* arena_stack, ArenaPool* arena_pool);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +010052 ~Transaction();
53
Vladimir Markob6e67922021-07-06 15:53:07 +010054 ArenaStack* GetArenaStack() {
55 return allocator_.GetArenaStack();
56 }
57
Sebastien Hertz1c80bec2015-02-03 11:58:06 +010058 void Abort(const std::string& abort_message)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -070059 REQUIRES_SHARED(Locks::mutator_lock_);
Sebastien Hertzb81e1cd2015-04-28 12:31:41 +020060 void ThrowAbortError(Thread* self, const std::string* abort_message)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -070061 REQUIRES_SHARED(Locks::mutator_lock_);
Vladimir Marko24c080f2021-07-06 14:04:30 +010062 bool IsAborted() const {
63 return aborted_;
64 }
Sebastien Hertz1c80bec2015-02-03 11:58:06 +010065
Chang Xing605fe242017-07-20 15:57:21 -070066 // If the transaction is rollbacking. Transactions will set this flag when they start rollbacking,
67 // because the nested transaction should be disabled when rollbacking to restore the memory.
Vladimir Marko24c080f2021-07-06 14:04:30 +010068 bool IsRollingBack() const {
69 return rolling_back_;
70 }
Chang Xing605fe242017-07-20 15:57:21 -070071
Chang Xing5a906fc2017-07-26 15:01:16 -070072 // If the transaction is in strict mode, then all access of static fields will be constrained,
73 // one class's clinit will not be allowed to read or modify another class's static fields, unless
74 // the transaction is aborted.
Vladimir Marko24c080f2021-07-06 14:04:30 +010075 bool IsStrict() const {
Vladimir Marko4d7b6892020-01-16 17:06:35 +000076 return strict_;
Vladimir Marko672c0802019-07-26 13:03:13 +010077 }
Chang Xing5a906fc2017-07-26 15:01:16 -070078
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +010079 // Record object field changes.
Mathieu Chartier38e954c2017-02-03 16:06:35 -080080 void RecordWriteFieldBoolean(mirror::Object* obj,
81 MemberOffset field_offset,
82 uint8_t value,
Vladimir Marko24c080f2021-07-06 14:04:30 +010083 bool is_volatile);
Mathieu Chartier38e954c2017-02-03 16:06:35 -080084 void RecordWriteFieldByte(mirror::Object* obj,
85 MemberOffset field_offset,
86 int8_t value,
Vladimir Marko24c080f2021-07-06 14:04:30 +010087 bool is_volatile);
Mathieu Chartier38e954c2017-02-03 16:06:35 -080088 void RecordWriteFieldChar(mirror::Object* obj,
89 MemberOffset field_offset,
90 uint16_t value,
Vladimir Marko24c080f2021-07-06 14:04:30 +010091 bool is_volatile);
Mathieu Chartier38e954c2017-02-03 16:06:35 -080092 void RecordWriteFieldShort(mirror::Object* obj,
93 MemberOffset field_offset,
94 int16_t value,
Vladimir Marko24c080f2021-07-06 14:04:30 +010095 bool is_volatile);
Mathieu Chartier38e954c2017-02-03 16:06:35 -080096 void RecordWriteField32(mirror::Object* obj,
97 MemberOffset field_offset,
98 uint32_t value,
Vladimir Marko24c080f2021-07-06 14:04:30 +010099 bool is_volatile);
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800100 void RecordWriteField64(mirror::Object* obj,
101 MemberOffset field_offset,
102 uint64_t value,
Vladimir Marko24c080f2021-07-06 14:04:30 +0100103 bool is_volatile);
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800104 void RecordWriteFieldReference(mirror::Object* obj,
105 MemberOffset field_offset,
106 mirror::Object* value,
Vladimir Marko24c080f2021-07-06 14:04:30 +0100107 bool is_volatile);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100108
109 // Record array change.
110 void RecordWriteArray(mirror::Array* array, size_t index, uint64_t value)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700111 REQUIRES_SHARED(Locks::mutator_lock_);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100112
113 // Record intern string table changes.
Mathieu Chartier9e868092016-10-31 14:58:04 -0700114 void RecordStrongStringInsertion(ObjPtr<mirror::String> s)
Vladimir Marko24c080f2021-07-06 14:04:30 +0100115 REQUIRES(Locks::intern_table_lock_);
Mathieu Chartier9e868092016-10-31 14:58:04 -0700116 void RecordWeakStringInsertion(ObjPtr<mirror::String> s)
Vladimir Marko24c080f2021-07-06 14:04:30 +0100117 REQUIRES(Locks::intern_table_lock_);
Mathieu Chartier9e868092016-10-31 14:58:04 -0700118 void RecordStrongStringRemoval(ObjPtr<mirror::String> s)
Vladimir Marko24c080f2021-07-06 14:04:30 +0100119 REQUIRES(Locks::intern_table_lock_);
Mathieu Chartier9e868092016-10-31 14:58:04 -0700120 void RecordWeakStringRemoval(ObjPtr<mirror::String> s)
Vladimir Marko24c080f2021-07-06 14:04:30 +0100121 REQUIRES(Locks::intern_table_lock_);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100122
Mathieu Chartierbb816d62016-09-07 10:17:46 -0700123 // Record resolve string.
Andreas Gampe8a0128a2016-11-28 07:38:35 -0800124 void RecordResolveString(ObjPtr<mirror::DexCache> dex_cache, dex::StringIndex string_idx)
Vladimir Marko24c080f2021-07-06 14:04:30 +0100125 REQUIRES_SHARED(Locks::mutator_lock_);
Mathieu Chartierbb816d62016-09-07 10:17:46 -0700126
Vladimir Markoe9a4a602021-06-22 16:33:34 +0100127 // Record resolve method type.
128 void RecordResolveMethodType(ObjPtr<mirror::DexCache> dex_cache, dex::ProtoIndex proto_idx)
Vladimir Marko24c080f2021-07-06 14:04:30 +0100129 REQUIRES_SHARED(Locks::mutator_lock_);
Vladimir Markoe9a4a602021-06-22 16:33:34 +0100130
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100131 // Abort transaction by undoing all recorded changes.
Sebastien Hertz1c80bec2015-02-03 11:58:06 +0100132 void Rollback()
Vladimir Marko24c080f2021-07-06 14:04:30 +0100133 REQUIRES_SHARED(Locks::mutator_lock_);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100134
Mathieu Chartierbb87e0f2015-04-03 11:21:55 -0700135 void VisitRoots(RootVisitor* visitor)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700136 REQUIRES_SHARED(Locks::mutator_lock_);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100137
Vladimir Marko24c080f2021-07-06 14:04:30 +0100138 bool ReadConstraint(ObjPtr<mirror::Object> obj) const
Chang Xingbd208d82017-07-12 14:53:17 -0700139 REQUIRES_SHARED(Locks::mutator_lock_);
140
Vladimir Marko24c080f2021-07-06 14:04:30 +0100141 bool WriteConstraint(ObjPtr<mirror::Object> obj) const
Chang Xingbd208d82017-07-12 14:53:17 -0700142 REQUIRES_SHARED(Locks::mutator_lock_);
143
Vladimir Marko24c080f2021-07-06 14:04:30 +0100144 bool WriteValueConstraint(ObjPtr<mirror::Object> value) const
Vladimir Marko149cdda2019-11-12 15:02:51 +0000145 REQUIRES_SHARED(Locks::mutator_lock_);
146
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100147 private:
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700148 class ObjectLog : public ValueObject {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100149 public:
Fred Shih37f05ef2014-07-16 18:38:08 -0700150 void LogBooleanValue(MemberOffset offset, uint8_t value, bool is_volatile);
151 void LogByteValue(MemberOffset offset, int8_t value, bool is_volatile);
152 void LogCharValue(MemberOffset offset, uint16_t value, bool is_volatile);
153 void LogShortValue(MemberOffset offset, int16_t value, bool is_volatile);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100154 void Log32BitsValue(MemberOffset offset, uint32_t value, bool is_volatile);
155 void Log64BitsValue(MemberOffset offset, uint64_t value, bool is_volatile);
156 void LogReferenceValue(MemberOffset offset, mirror::Object* obj, bool is_volatile);
157
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800158 void Undo(mirror::Object* obj) const REQUIRES_SHARED(Locks::mutator_lock_);
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700159 void VisitRoots(RootVisitor* visitor) REQUIRES_SHARED(Locks::mutator_lock_);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100160
161 size_t Size() const {
162 return field_values_.size();
163 }
164
Vladimir Markob6e67922021-07-06 15:53:07 +0100165 explicit ObjectLog(ScopedArenaAllocator* allocator)
166 : field_values_(std::less<uint32_t>(), allocator->Adapter(kArenaAllocTransaction)) {}
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800167 ObjectLog(ObjectLog&& log) = default;
168
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100169 private:
170 enum FieldValueKind {
Fred Shih37f05ef2014-07-16 18:38:08 -0700171 kBoolean,
172 kByte,
173 kChar,
174 kShort,
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100175 k32Bits,
176 k64Bits,
177 kReference
178 };
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700179 struct FieldValue : public ValueObject {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100180 // TODO use JValue instead ?
181 uint64_t value;
182 FieldValueKind kind;
183 bool is_volatile;
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800184
Andreas Gamped9911ee2017-03-27 13:27:24 -0700185 FieldValue() : value(0), kind(FieldValueKind::kBoolean), is_volatile(false) {}
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800186 FieldValue(FieldValue&& log) = default;
187
188 private:
189 DISALLOW_COPY_AND_ASSIGN(FieldValue);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100190 };
191
Fred Shih37f05ef2014-07-16 18:38:08 -0700192 void LogValue(FieldValueKind kind, MemberOffset offset, uint64_t value, bool is_volatile);
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800193 void UndoFieldWrite(mirror::Object* obj,
194 MemberOffset field_offset,
195 const FieldValue& field_value) const REQUIRES_SHARED(Locks::mutator_lock_);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100196
197 // Maps field's offset to its value.
Vladimir Markob6e67922021-07-06 15:53:07 +0100198 ScopedArenaSafeMap<uint32_t, FieldValue> field_values_;
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800199
200 DISALLOW_COPY_AND_ASSIGN(ObjectLog);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100201 };
202
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700203 class ArrayLog : public ValueObject {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100204 public:
205 void LogValue(size_t index, uint64_t value);
206
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800207 void Undo(mirror::Array* obj) const REQUIRES_SHARED(Locks::mutator_lock_);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100208
209 size_t Size() const {
210 return array_values_.size();
211 }
212
Vladimir Markob6e67922021-07-06 15:53:07 +0100213 explicit ArrayLog(ScopedArenaAllocator* allocator)
214 : array_values_(std::less<size_t>(), allocator->Adapter(kArenaAllocTransaction)) {}
215
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800216 ArrayLog(ArrayLog&& log) = default;
217
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100218 private:
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800219 void UndoArrayWrite(mirror::Array* array,
220 Primitive::Type array_type,
221 size_t index,
222 uint64_t value) const REQUIRES_SHARED(Locks::mutator_lock_);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100223
224 // Maps index to value.
225 // TODO use JValue instead ?
Vladimir Markob6e67922021-07-06 15:53:07 +0100226 ScopedArenaSafeMap<size_t, uint64_t> array_values_;
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800227
228 DISALLOW_COPY_AND_ASSIGN(ArrayLog);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100229 };
230
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700231 class InternStringLog : public ValueObject {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100232 public:
233 enum StringKind {
234 kStrongString,
235 kWeakString
236 };
237 enum StringOp {
238 kInsert,
239 kRemove
240 };
Mathieu Chartier9e868092016-10-31 14:58:04 -0700241 InternStringLog(ObjPtr<mirror::String> s, StringKind kind, StringOp op);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100242
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800243 void Undo(InternTable* intern_table) const
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700244 REQUIRES_SHARED(Locks::mutator_lock_)
Mathieu Chartier90443472015-07-16 20:32:27 -0700245 REQUIRES(Locks::intern_table_lock_);
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700246 void VisitRoots(RootVisitor* visitor) REQUIRES_SHARED(Locks::mutator_lock_);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100247
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800248 InternStringLog() = default;
249 InternStringLog(InternStringLog&& log) = default;
250
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100251 private:
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800252 mutable GcRoot<mirror::String> str_;
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700253 const StringKind string_kind_;
254 const StringOp string_op_;
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800255
256 DISALLOW_COPY_AND_ASSIGN(InternStringLog);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100257 };
258
Mathieu Chartierbb816d62016-09-07 10:17:46 -0700259 class ResolveStringLog : public ValueObject {
260 public:
Andreas Gampe8a0128a2016-11-28 07:38:35 -0800261 ResolveStringLog(ObjPtr<mirror::DexCache> dex_cache, dex::StringIndex string_idx);
Mathieu Chartierbb816d62016-09-07 10:17:46 -0700262
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800263 void Undo() const REQUIRES_SHARED(Locks::mutator_lock_);
Mathieu Chartierbb816d62016-09-07 10:17:46 -0700264
265 void VisitRoots(RootVisitor* visitor) REQUIRES_SHARED(Locks::mutator_lock_);
266
267 private:
268 GcRoot<mirror::DexCache> dex_cache_;
Andreas Gampe8a0128a2016-11-28 07:38:35 -0800269 const dex::StringIndex string_idx_;
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800270
271 DISALLOW_COPY_AND_ASSIGN(ResolveStringLog);
Mathieu Chartierbb816d62016-09-07 10:17:46 -0700272 };
273
Vladimir Markoe9a4a602021-06-22 16:33:34 +0100274 class ResolveMethodTypeLog : public ValueObject {
275 public:
276 ResolveMethodTypeLog(ObjPtr<mirror::DexCache> dex_cache, dex::ProtoIndex proto_idx);
277
278 void Undo() const REQUIRES_SHARED(Locks::mutator_lock_);
279
280 void VisitRoots(RootVisitor* visitor) REQUIRES_SHARED(Locks::mutator_lock_);
281
282 private:
283 GcRoot<mirror::DexCache> dex_cache_;
284 const dex::ProtoIndex proto_idx_;
285
286 DISALLOW_COPY_AND_ASSIGN(ResolveMethodTypeLog);
287 };
288
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800289 void LogInternedString(InternStringLog&& log)
Vladimir Marko24c080f2021-07-06 14:04:30 +0100290 REQUIRES(Locks::intern_table_lock_);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100291
292 void UndoObjectModifications()
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700293 REQUIRES_SHARED(Locks::mutator_lock_);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100294 void UndoArrayModifications()
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700295 REQUIRES_SHARED(Locks::mutator_lock_);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100296 void UndoInternStringTableModifications()
Mathieu Chartier90443472015-07-16 20:32:27 -0700297 REQUIRES(Locks::intern_table_lock_)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700298 REQUIRES_SHARED(Locks::mutator_lock_);
Mathieu Chartierbb816d62016-09-07 10:17:46 -0700299 void UndoResolveStringModifications()
Mathieu Chartierbb816d62016-09-07 10:17:46 -0700300 REQUIRES_SHARED(Locks::mutator_lock_);
Vladimir Markoe9a4a602021-06-22 16:33:34 +0100301 void UndoResolveMethodTypeModifications()
Vladimir Markoe9a4a602021-06-22 16:33:34 +0100302 REQUIRES_SHARED(Locks::mutator_lock_);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100303
Vladimir Markob6e67922021-07-06 15:53:07 +0100304 void VisitObjectLogs(RootVisitor* visitor, ArenaStack* arena_stack)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700305 REQUIRES_SHARED(Locks::mutator_lock_);
Vladimir Markob6e67922021-07-06 15:53:07 +0100306 void VisitArrayLogs(RootVisitor* visitor, ArenaStack* arena_stack)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700307 REQUIRES_SHARED(Locks::mutator_lock_);
Mathieu Chartierbb816d62016-09-07 10:17:46 -0700308 void VisitInternStringLogs(RootVisitor* visitor)
Mathieu Chartierbb816d62016-09-07 10:17:46 -0700309 REQUIRES_SHARED(Locks::mutator_lock_);
310 void VisitResolveStringLogs(RootVisitor* visitor)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700311 REQUIRES_SHARED(Locks::mutator_lock_);
Vladimir Markoe9a4a602021-06-22 16:33:34 +0100312 void VisitResolveMethodTypeLogs(RootVisitor* visitor)
Vladimir Markoe9a4a602021-06-22 16:33:34 +0100313 REQUIRES_SHARED(Locks::mutator_lock_);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100314
Vladimir Marko24c080f2021-07-06 14:04:30 +0100315 const std::string& GetAbortMessage() const;
Sebastien Hertz1c80bec2015-02-03 11:58:06 +0100316
Vladimir Markob6e67922021-07-06 15:53:07 +0100317 ObjectLog& GetOrCreateObjectLog(mirror::Object* obj);
318
319 // The top-level transaction creates an `ArenaStack` which is then
320 // passed down to nested transactions.
321 std::optional<ArenaStack> arena_stack_;
322 // The allocator uses the `ArenaStack` from the top-level transaction.
323 ScopedArenaAllocator allocator_;
324
325 ScopedArenaSafeMap<mirror::Object*, ObjectLog> object_logs_;
Roland Levillain4f623272021-07-07 16:32:26 +0100326 ScopedArenaSafeMap<mirror::Array*, ArrayLog> array_logs_;
Vladimir Markob6e67922021-07-06 15:53:07 +0100327 ScopedArenaForwardList<InternStringLog> intern_string_logs_;
328 ScopedArenaForwardList<ResolveStringLog> resolve_string_logs_;
329 ScopedArenaForwardList<ResolveMethodTypeLog> resolve_method_type_logs_;
Vladimir Marko24c080f2021-07-06 14:04:30 +0100330 bool aborted_;
Chang Xing605fe242017-07-20 15:57:21 -0700331 bool rolling_back_; // Single thread, no race.
Vladimir Marko672c0802019-07-26 13:03:13 +0100332 gc::Heap* const heap_;
Vladimir Marko4d7b6892020-01-16 17:06:35 +0000333 const bool strict_;
Vladimir Marko24c080f2021-07-06 14:04:30 +0100334 std::string abort_message_;
335 mirror::Class* root_;
336 const char* assert_no_new_records_reason_;
Vladimir Markob68bb7a2020-03-17 10:55:25 +0000337
338 friend class ScopedAssertNoNewTransactionRecords;
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100339
340 DISALLOW_COPY_AND_ASSIGN(Transaction);
341};
342
Vladimir Markob68bb7a2020-03-17 10:55:25 +0000343class ScopedAssertNoNewTransactionRecords {
344 public:
345 explicit ScopedAssertNoNewTransactionRecords(const char* reason)
346 : transaction_(kIsDebugBuild ? InstallAssertion(reason) : nullptr) {}
347
348 ~ScopedAssertNoNewTransactionRecords() {
349 if (kIsDebugBuild && transaction_ != nullptr) {
350 RemoveAssertion(transaction_);
351 }
352 }
353
354 private:
355 static Transaction* InstallAssertion(const char* reason);
356 static void RemoveAssertion(Transaction* transaction);
357
358 Transaction* transaction_;
359};
360
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100361} // namespace art
362
363#endif // ART_RUNTIME_TRANSACTION_H_