blob: 184280f9c86b24f29c3d10a4a5d9bad76bf939f7 [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
20#include "base/macros.h"
21#include "base/mutex.h"
David Sehr67bf42e2018-02-26 16:43:04 -080022#include "base/safe_map.h"
Ian Rogers6a3c1fc2014-10-31 00:33:20 -070023#include "base/value_object.h"
David Sehr9e734c72018-01-04 17:56:19 -080024#include "dex/dex_file_types.h"
David Sehr67bf42e2018-02-26 16:43:04 -080025#include "dex/primitive.h"
Mathieu Chartiere34fa1d2015-01-14 14:55:47 -080026#include "gc_root.h"
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +010027#include "offsets.h"
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +010028
29#include <list>
30#include <map>
31
32namespace art {
Vladimir Marko672c0802019-07-26 13:03:13 +010033namespace gc {
34class Heap;
35} // namespace gc
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +010036namespace mirror {
37class Array;
Chang Xingcade5c32017-07-20 17:56:26 -070038class Class;
Mathieu Chartierbb816d62016-09-07 10:17:46 -070039class DexCache;
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +010040class Object;
41class String;
Andreas Gampedeae7db2017-05-30 09:56:41 -070042} // namespace mirror
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +010043class InternTable;
Vladimir Marko672c0802019-07-26 13:03:13 +010044template<class MirrorType> class ObjPtr;
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +010045
Roland Levillainbbc6e7e2018-08-24 16:58:47 +010046class Transaction final {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +010047 public:
Sebastien Hertz2fd7e692015-04-02 11:11:19 +020048 static constexpr const char* kAbortExceptionDescriptor = "dalvik.system.TransactionAbortError";
49 static constexpr const char* kAbortExceptionSignature = "Ldalvik/system/TransactionAbortError;";
50
Vladimir Marko672c0802019-07-26 13:03:13 +010051 Transaction(bool strict, mirror::Class* root);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +010052 ~Transaction();
53
Sebastien Hertz1c80bec2015-02-03 11:58:06 +010054 void Abort(const std::string& abort_message)
Mathieu Chartier90443472015-07-16 20:32:27 -070055 REQUIRES(!log_lock_)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -070056 REQUIRES_SHARED(Locks::mutator_lock_);
Sebastien Hertzb81e1cd2015-04-28 12:31:41 +020057 void ThrowAbortError(Thread* self, const std::string* abort_message)
Mathieu Chartier90443472015-07-16 20:32:27 -070058 REQUIRES(!log_lock_)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -070059 REQUIRES_SHARED(Locks::mutator_lock_);
Mathieu Chartier90443472015-07-16 20:32:27 -070060 bool IsAborted() REQUIRES(!log_lock_);
Sebastien Hertz1c80bec2015-02-03 11:58:06 +010061
Chang Xing605fe242017-07-20 15:57:21 -070062 // If the transaction is rollbacking. Transactions will set this flag when they start rollbacking,
63 // because the nested transaction should be disabled when rollbacking to restore the memory.
64 bool IsRollingBack();
65
Chang Xing5a906fc2017-07-26 15:01:16 -070066 // If the transaction is in strict mode, then all access of static fields will be constrained,
67 // one class's clinit will not be allowed to read or modify another class's static fields, unless
68 // the transaction is aborted.
Vladimir Marko672c0802019-07-26 13:03:13 +010069 bool IsStrict() {
Vladimir Marko4d7b6892020-01-16 17:06:35 +000070 return strict_;
Vladimir Marko672c0802019-07-26 13:03:13 +010071 }
Chang Xing5a906fc2017-07-26 15:01:16 -070072
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +010073 // Record object field changes.
Mathieu Chartier38e954c2017-02-03 16:06:35 -080074 void RecordWriteFieldBoolean(mirror::Object* obj,
75 MemberOffset field_offset,
76 uint8_t value,
Fred Shih37f05ef2014-07-16 18:38:08 -070077 bool is_volatile)
Mathieu Chartier90443472015-07-16 20:32:27 -070078 REQUIRES(!log_lock_);
Mathieu Chartier38e954c2017-02-03 16:06:35 -080079 void RecordWriteFieldByte(mirror::Object* obj,
80 MemberOffset field_offset,
81 int8_t value,
Fred Shih37f05ef2014-07-16 18:38:08 -070082 bool is_volatile)
Mathieu Chartier90443472015-07-16 20:32:27 -070083 REQUIRES(!log_lock_);
Mathieu Chartier38e954c2017-02-03 16:06:35 -080084 void RecordWriteFieldChar(mirror::Object* obj,
85 MemberOffset field_offset,
86 uint16_t value,
87 bool is_volatile)
88 REQUIRES(!log_lock_);
89 void RecordWriteFieldShort(mirror::Object* obj,
90 MemberOffset field_offset,
91 int16_t value,
Fred Shih37f05ef2014-07-16 18:38:08 -070092 bool is_volatile)
Mathieu Chartier90443472015-07-16 20:32:27 -070093 REQUIRES(!log_lock_);
Mathieu Chartier38e954c2017-02-03 16:06:35 -080094 void RecordWriteField32(mirror::Object* obj,
95 MemberOffset field_offset,
96 uint32_t value,
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +010097 bool is_volatile)
Mathieu Chartier90443472015-07-16 20:32:27 -070098 REQUIRES(!log_lock_);
Mathieu Chartier38e954c2017-02-03 16:06:35 -080099 void RecordWriteField64(mirror::Object* obj,
100 MemberOffset field_offset,
101 uint64_t value,
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100102 bool is_volatile)
Mathieu Chartier90443472015-07-16 20:32:27 -0700103 REQUIRES(!log_lock_);
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800104 void RecordWriteFieldReference(mirror::Object* obj,
105 MemberOffset field_offset,
106 mirror::Object* value,
107 bool is_volatile)
Mathieu Chartier90443472015-07-16 20:32:27 -0700108 REQUIRES(!log_lock_);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100109
110 // Record array change.
111 void RecordWriteArray(mirror::Array* array, size_t index, uint64_t value)
Mathieu Chartier90443472015-07-16 20:32:27 -0700112 REQUIRES(!log_lock_)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700113 REQUIRES_SHARED(Locks::mutator_lock_);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100114
115 // Record intern string table changes.
Mathieu Chartier9e868092016-10-31 14:58:04 -0700116 void RecordStrongStringInsertion(ObjPtr<mirror::String> s)
Mathieu Chartier90443472015-07-16 20:32:27 -0700117 REQUIRES(Locks::intern_table_lock_)
118 REQUIRES(!log_lock_);
Mathieu Chartier9e868092016-10-31 14:58:04 -0700119 void RecordWeakStringInsertion(ObjPtr<mirror::String> s)
Mathieu Chartier90443472015-07-16 20:32:27 -0700120 REQUIRES(Locks::intern_table_lock_)
121 REQUIRES(!log_lock_);
Mathieu Chartier9e868092016-10-31 14:58:04 -0700122 void RecordStrongStringRemoval(ObjPtr<mirror::String> s)
Mathieu Chartier90443472015-07-16 20:32:27 -0700123 REQUIRES(Locks::intern_table_lock_)
124 REQUIRES(!log_lock_);
Mathieu Chartier9e868092016-10-31 14:58:04 -0700125 void RecordWeakStringRemoval(ObjPtr<mirror::String> s)
Mathieu Chartier90443472015-07-16 20:32:27 -0700126 REQUIRES(Locks::intern_table_lock_)
127 REQUIRES(!log_lock_);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100128
Mathieu Chartierbb816d62016-09-07 10:17:46 -0700129 // Record resolve string.
Andreas Gampe8a0128a2016-11-28 07:38:35 -0800130 void RecordResolveString(ObjPtr<mirror::DexCache> dex_cache, dex::StringIndex string_idx)
Mathieu Chartierbb816d62016-09-07 10:17:46 -0700131 REQUIRES_SHARED(Locks::mutator_lock_)
132 REQUIRES(!log_lock_);
133
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100134 // Abort transaction by undoing all recorded changes.
Sebastien Hertz1c80bec2015-02-03 11:58:06 +0100135 void Rollback()
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700136 REQUIRES_SHARED(Locks::mutator_lock_)
Mathieu Chartier90443472015-07-16 20:32:27 -0700137 REQUIRES(!log_lock_);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100138
Mathieu Chartierbb87e0f2015-04-03 11:21:55 -0700139 void VisitRoots(RootVisitor* visitor)
Mathieu Chartier90443472015-07-16 20:32:27 -0700140 REQUIRES(!log_lock_)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700141 REQUIRES_SHARED(Locks::mutator_lock_);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100142
Vladimir Marko4d7b6892020-01-16 17:06:35 +0000143 bool ReadConstraint(Thread* self, ObjPtr<mirror::Object> obj)
Chang Xingbd208d82017-07-12 14:53:17 -0700144 REQUIRES(!log_lock_)
145 REQUIRES_SHARED(Locks::mutator_lock_);
146
Vladimir Marko4d7b6892020-01-16 17:06:35 +0000147 bool WriteConstraint(Thread* self, ObjPtr<mirror::Object> obj)
Chang Xingbd208d82017-07-12 14:53:17 -0700148 REQUIRES(!log_lock_)
149 REQUIRES_SHARED(Locks::mutator_lock_);
150
Vladimir Marko149cdda2019-11-12 15:02:51 +0000151 bool WriteValueConstraint(Thread* self, ObjPtr<mirror::Object> value)
152 REQUIRES(!log_lock_)
153 REQUIRES_SHARED(Locks::mutator_lock_);
154
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100155 private:
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700156 class ObjectLog : public ValueObject {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100157 public:
Fred Shih37f05ef2014-07-16 18:38:08 -0700158 void LogBooleanValue(MemberOffset offset, uint8_t value, bool is_volatile);
159 void LogByteValue(MemberOffset offset, int8_t value, bool is_volatile);
160 void LogCharValue(MemberOffset offset, uint16_t value, bool is_volatile);
161 void LogShortValue(MemberOffset offset, int16_t value, bool is_volatile);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100162 void Log32BitsValue(MemberOffset offset, uint32_t value, bool is_volatile);
163 void Log64BitsValue(MemberOffset offset, uint64_t value, bool is_volatile);
164 void LogReferenceValue(MemberOffset offset, mirror::Object* obj, bool is_volatile);
165
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800166 void Undo(mirror::Object* obj) const REQUIRES_SHARED(Locks::mutator_lock_);
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700167 void VisitRoots(RootVisitor* visitor) REQUIRES_SHARED(Locks::mutator_lock_);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100168
169 size_t Size() const {
170 return field_values_.size();
171 }
172
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800173 ObjectLog() = default;
174 ObjectLog(ObjectLog&& log) = default;
175
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100176 private:
177 enum FieldValueKind {
Fred Shih37f05ef2014-07-16 18:38:08 -0700178 kBoolean,
179 kByte,
180 kChar,
181 kShort,
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100182 k32Bits,
183 k64Bits,
184 kReference
185 };
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700186 struct FieldValue : public ValueObject {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100187 // TODO use JValue instead ?
188 uint64_t value;
189 FieldValueKind kind;
190 bool is_volatile;
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800191
Andreas Gamped9911ee2017-03-27 13:27:24 -0700192 FieldValue() : value(0), kind(FieldValueKind::kBoolean), is_volatile(false) {}
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800193 FieldValue(FieldValue&& log) = default;
194
195 private:
196 DISALLOW_COPY_AND_ASSIGN(FieldValue);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100197 };
198
Fred Shih37f05ef2014-07-16 18:38:08 -0700199 void LogValue(FieldValueKind kind, MemberOffset offset, uint64_t value, bool is_volatile);
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800200 void UndoFieldWrite(mirror::Object* obj,
201 MemberOffset field_offset,
202 const FieldValue& field_value) const REQUIRES_SHARED(Locks::mutator_lock_);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100203
204 // Maps field's offset to its value.
205 std::map<uint32_t, FieldValue> field_values_;
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800206
207 DISALLOW_COPY_AND_ASSIGN(ObjectLog);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100208 };
209
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700210 class ArrayLog : public ValueObject {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100211 public:
212 void LogValue(size_t index, uint64_t value);
213
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800214 void Undo(mirror::Array* obj) const REQUIRES_SHARED(Locks::mutator_lock_);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100215
216 size_t Size() const {
217 return array_values_.size();
218 }
219
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800220 ArrayLog() = default;
221 ArrayLog(ArrayLog&& log) = default;
222
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100223 private:
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800224 void UndoArrayWrite(mirror::Array* array,
225 Primitive::Type array_type,
226 size_t index,
227 uint64_t value) const REQUIRES_SHARED(Locks::mutator_lock_);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100228
229 // Maps index to value.
230 // TODO use JValue instead ?
231 std::map<size_t, uint64_t> array_values_;
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800232
233 DISALLOW_COPY_AND_ASSIGN(ArrayLog);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100234 };
235
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700236 class InternStringLog : public ValueObject {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100237 public:
238 enum StringKind {
239 kStrongString,
240 kWeakString
241 };
242 enum StringOp {
243 kInsert,
244 kRemove
245 };
Mathieu Chartier9e868092016-10-31 14:58:04 -0700246 InternStringLog(ObjPtr<mirror::String> s, StringKind kind, StringOp op);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100247
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800248 void Undo(InternTable* intern_table) const
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700249 REQUIRES_SHARED(Locks::mutator_lock_)
Mathieu Chartier90443472015-07-16 20:32:27 -0700250 REQUIRES(Locks::intern_table_lock_);
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700251 void VisitRoots(RootVisitor* visitor) REQUIRES_SHARED(Locks::mutator_lock_);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100252
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800253 InternStringLog() = default;
254 InternStringLog(InternStringLog&& log) = default;
255
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100256 private:
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800257 mutable GcRoot<mirror::String> str_;
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700258 const StringKind string_kind_;
259 const StringOp string_op_;
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800260
261 DISALLOW_COPY_AND_ASSIGN(InternStringLog);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100262 };
263
Mathieu Chartierbb816d62016-09-07 10:17:46 -0700264 class ResolveStringLog : public ValueObject {
265 public:
Andreas Gampe8a0128a2016-11-28 07:38:35 -0800266 ResolveStringLog(ObjPtr<mirror::DexCache> dex_cache, dex::StringIndex string_idx);
Mathieu Chartierbb816d62016-09-07 10:17:46 -0700267
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800268 void Undo() const REQUIRES_SHARED(Locks::mutator_lock_);
Mathieu Chartierbb816d62016-09-07 10:17:46 -0700269
270 void VisitRoots(RootVisitor* visitor) REQUIRES_SHARED(Locks::mutator_lock_);
271
272 private:
273 GcRoot<mirror::DexCache> dex_cache_;
Andreas Gampe8a0128a2016-11-28 07:38:35 -0800274 const dex::StringIndex string_idx_;
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800275
276 DISALLOW_COPY_AND_ASSIGN(ResolveStringLog);
Mathieu Chartierbb816d62016-09-07 10:17:46 -0700277 };
278
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800279 void LogInternedString(InternStringLog&& log)
Mathieu Chartier90443472015-07-16 20:32:27 -0700280 REQUIRES(Locks::intern_table_lock_)
281 REQUIRES(!log_lock_);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100282
283 void UndoObjectModifications()
Mathieu Chartier90443472015-07-16 20:32:27 -0700284 REQUIRES(log_lock_)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700285 REQUIRES_SHARED(Locks::mutator_lock_);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100286 void UndoArrayModifications()
Mathieu Chartier90443472015-07-16 20:32:27 -0700287 REQUIRES(log_lock_)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700288 REQUIRES_SHARED(Locks::mutator_lock_);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100289 void UndoInternStringTableModifications()
Mathieu Chartier90443472015-07-16 20:32:27 -0700290 REQUIRES(Locks::intern_table_lock_)
291 REQUIRES(log_lock_)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700292 REQUIRES_SHARED(Locks::mutator_lock_);
Mathieu Chartierbb816d62016-09-07 10:17:46 -0700293 void UndoResolveStringModifications()
294 REQUIRES(log_lock_)
295 REQUIRES_SHARED(Locks::mutator_lock_);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100296
Mathieu Chartierbb87e0f2015-04-03 11:21:55 -0700297 void VisitObjectLogs(RootVisitor* visitor)
Mathieu Chartier90443472015-07-16 20:32:27 -0700298 REQUIRES(log_lock_)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700299 REQUIRES_SHARED(Locks::mutator_lock_);
Mathieu Chartierbb87e0f2015-04-03 11:21:55 -0700300 void VisitArrayLogs(RootVisitor* visitor)
Mathieu Chartier90443472015-07-16 20:32:27 -0700301 REQUIRES(log_lock_)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700302 REQUIRES_SHARED(Locks::mutator_lock_);
Mathieu Chartierbb816d62016-09-07 10:17:46 -0700303 void VisitInternStringLogs(RootVisitor* visitor)
304 REQUIRES(log_lock_)
305 REQUIRES_SHARED(Locks::mutator_lock_);
306 void VisitResolveStringLogs(RootVisitor* visitor)
Mathieu Chartier90443472015-07-16 20:32:27 -0700307 REQUIRES(log_lock_)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700308 REQUIRES_SHARED(Locks::mutator_lock_);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100309
Mathieu Chartier90443472015-07-16 20:32:27 -0700310 const std::string& GetAbortMessage() REQUIRES(!log_lock_);
Sebastien Hertz1c80bec2015-02-03 11:58:06 +0100311
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100312 Mutex log_lock_ ACQUIRED_AFTER(Locks::intern_table_lock_);
313 std::map<mirror::Object*, ObjectLog> object_logs_ GUARDED_BY(log_lock_);
314 std::map<mirror::Array*, ArrayLog> array_logs_ GUARDED_BY(log_lock_);
315 std::list<InternStringLog> intern_string_logs_ GUARDED_BY(log_lock_);
Mathieu Chartierbb816d62016-09-07 10:17:46 -0700316 std::list<ResolveStringLog> resolve_string_logs_ GUARDED_BY(log_lock_);
Sebastien Hertz1c80bec2015-02-03 11:58:06 +0100317 bool aborted_ GUARDED_BY(log_lock_);
Chang Xing605fe242017-07-20 15:57:21 -0700318 bool rolling_back_; // Single thread, no race.
Vladimir Marko672c0802019-07-26 13:03:13 +0100319 gc::Heap* const heap_;
Vladimir Marko4d7b6892020-01-16 17:06:35 +0000320 const bool strict_;
Sebastien Hertz1c80bec2015-02-03 11:58:06 +0100321 std::string abort_message_ GUARDED_BY(log_lock_);
Chang Xingcade5c32017-07-20 17:56:26 -0700322 mirror::Class* root_ GUARDED_BY(log_lock_);
Vladimir Markob68bb7a2020-03-17 10:55:25 +0000323 const char* assert_no_new_records_reason_ GUARDED_BY(log_lock_);
324
325 friend class ScopedAssertNoNewTransactionRecords;
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100326
327 DISALLOW_COPY_AND_ASSIGN(Transaction);
328};
329
Vladimir Markob68bb7a2020-03-17 10:55:25 +0000330class ScopedAssertNoNewTransactionRecords {
331 public:
332 explicit ScopedAssertNoNewTransactionRecords(const char* reason)
333 : transaction_(kIsDebugBuild ? InstallAssertion(reason) : nullptr) {}
334
335 ~ScopedAssertNoNewTransactionRecords() {
336 if (kIsDebugBuild && transaction_ != nullptr) {
337 RemoveAssertion(transaction_);
338 }
339 }
340
341 private:
342 static Transaction* InstallAssertion(const char* reason);
343 static void RemoveAssertion(Transaction* transaction);
344
345 Transaction* transaction_;
346};
347
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100348} // namespace art
349
350#endif // ART_RUNTIME_TRANSACTION_H_