xref: /aosp_15_r20/art/dex2oat/aot_class_linker.cc (revision 795d594fd825385562da6b089ea9b2033f3abf5a)
1*795d594fSAndroid Build Coastguard Worker /*
2*795d594fSAndroid Build Coastguard Worker  * Copyright (C) 2017 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 #include "aot_class_linker.h"
18*795d594fSAndroid Build Coastguard Worker 
19*795d594fSAndroid Build Coastguard Worker #include "base/stl_util.h"
20*795d594fSAndroid Build Coastguard Worker #include "class_status.h"
21*795d594fSAndroid Build Coastguard Worker #include "compiler_callbacks.h"
22*795d594fSAndroid Build Coastguard Worker #include "dex/class_reference.h"
23*795d594fSAndroid Build Coastguard Worker #include "gc/heap.h"
24*795d594fSAndroid Build Coastguard Worker #include "handle_scope-inl.h"
25*795d594fSAndroid Build Coastguard Worker #include "interpreter/interpreter_switch_impl.h"
26*795d594fSAndroid Build Coastguard Worker #include "mirror/class-inl.h"
27*795d594fSAndroid Build Coastguard Worker #include "runtime.h"
28*795d594fSAndroid Build Coastguard Worker #include "scoped_thread_state_change-inl.h"
29*795d594fSAndroid Build Coastguard Worker #include "transaction.h"
30*795d594fSAndroid Build Coastguard Worker #include "verifier/verifier_enums.h"
31*795d594fSAndroid Build Coastguard Worker 
32*795d594fSAndroid Build Coastguard Worker namespace art HIDDEN {
33*795d594fSAndroid Build Coastguard Worker 
AotClassLinker(InternTable * intern_table)34*795d594fSAndroid Build Coastguard Worker AotClassLinker::AotClassLinker(InternTable* intern_table)
35*795d594fSAndroid Build Coastguard Worker     : ClassLinker(intern_table, /*fast_class_not_found_exceptions=*/ false),
36*795d594fSAndroid Build Coastguard Worker       preinitialization_transactions_() {}
37*795d594fSAndroid Build Coastguard Worker 
~AotClassLinker()38*795d594fSAndroid Build Coastguard Worker AotClassLinker::~AotClassLinker() {}
39*795d594fSAndroid Build Coastguard Worker 
CanAllocClass()40*795d594fSAndroid Build Coastguard Worker bool AotClassLinker::CanAllocClass() {
41*795d594fSAndroid Build Coastguard Worker   // AllocClass doesn't work under transaction, so we abort.
42*795d594fSAndroid Build Coastguard Worker   if (IsActiveTransaction()) {
43*795d594fSAndroid Build Coastguard Worker     AbortTransactionF(Thread::Current(), "Can't resolve type within transaction.");
44*795d594fSAndroid Build Coastguard Worker     return false;
45*795d594fSAndroid Build Coastguard Worker   }
46*795d594fSAndroid Build Coastguard Worker   return ClassLinker::CanAllocClass();
47*795d594fSAndroid Build Coastguard Worker }
48*795d594fSAndroid Build Coastguard Worker 
49*795d594fSAndroid Build Coastguard Worker // Wrap the original InitializeClass with creation of transaction when in strict mode.
InitializeClass(Thread * self,Handle<mirror::Class> klass,bool can_init_statics,bool can_init_parents)50*795d594fSAndroid Build Coastguard Worker bool AotClassLinker::InitializeClass(Thread* self,
51*795d594fSAndroid Build Coastguard Worker                                      Handle<mirror::Class> klass,
52*795d594fSAndroid Build Coastguard Worker                                      bool can_init_statics,
53*795d594fSAndroid Build Coastguard Worker                                      bool can_init_parents) {
54*795d594fSAndroid Build Coastguard Worker   bool strict_mode = IsActiveStrictTransactionMode();
55*795d594fSAndroid Build Coastguard Worker 
56*795d594fSAndroid Build Coastguard Worker   DCHECK(klass != nullptr);
57*795d594fSAndroid Build Coastguard Worker   if (klass->IsInitialized() || klass->IsInitializing()) {
58*795d594fSAndroid Build Coastguard Worker     return ClassLinker::InitializeClass(self, klass, can_init_statics, can_init_parents);
59*795d594fSAndroid Build Coastguard Worker   }
60*795d594fSAndroid Build Coastguard Worker 
61*795d594fSAndroid Build Coastguard Worker   // When compiling a boot image extension, do not initialize a class defined
62*795d594fSAndroid Build Coastguard Worker   // in a dex file belonging to the boot image we're compiling against.
63*795d594fSAndroid Build Coastguard Worker   // However, we must allow the initialization of TransactionAbortError,
64*795d594fSAndroid Build Coastguard Worker   // VerifyError, etc. outside of a transaction.
65*795d594fSAndroid Build Coastguard Worker   if (!strict_mode &&
66*795d594fSAndroid Build Coastguard Worker       Runtime::Current()->GetHeap()->ObjectIsInBootImageSpace(klass->GetDexCache())) {
67*795d594fSAndroid Build Coastguard Worker     if (IsActiveTransaction()) {
68*795d594fSAndroid Build Coastguard Worker       AbortTransactionF(self,
69*795d594fSAndroid Build Coastguard Worker                         "Can't initialize %s because it is defined in a boot image dex file.",
70*795d594fSAndroid Build Coastguard Worker                         klass->PrettyTypeOf().c_str());
71*795d594fSAndroid Build Coastguard Worker       return false;
72*795d594fSAndroid Build Coastguard Worker     }
73*795d594fSAndroid Build Coastguard Worker     CHECK(klass->IsThrowableClass()) << klass->PrettyDescriptor();
74*795d594fSAndroid Build Coastguard Worker   }
75*795d594fSAndroid Build Coastguard Worker 
76*795d594fSAndroid Build Coastguard Worker   // When in strict_mode, don't initialize a class if it belongs to boot but not initialized.
77*795d594fSAndroid Build Coastguard Worker   if (strict_mode && klass->IsBootStrapClassLoaded()) {
78*795d594fSAndroid Build Coastguard Worker     AbortTransactionF(self,
79*795d594fSAndroid Build Coastguard Worker                       "Can't resolve %s because it is an uninitialized boot class.",
80*795d594fSAndroid Build Coastguard Worker                       klass->PrettyTypeOf().c_str());
81*795d594fSAndroid Build Coastguard Worker     return false;
82*795d594fSAndroid Build Coastguard Worker   }
83*795d594fSAndroid Build Coastguard Worker 
84*795d594fSAndroid Build Coastguard Worker   // Don't initialize klass if it's superclass is not initialized, because superclass might abort
85*795d594fSAndroid Build Coastguard Worker   // the transaction and rolled back after klass's change is commited.
86*795d594fSAndroid Build Coastguard Worker   if (strict_mode && !klass->IsInterface() && klass->HasSuperClass()) {
87*795d594fSAndroid Build Coastguard Worker     if (klass->GetSuperClass()->GetStatus() == ClassStatus::kInitializing) {
88*795d594fSAndroid Build Coastguard Worker       AbortTransactionF(self,
89*795d594fSAndroid Build Coastguard Worker                         "Can't resolve %s because it's superclass is not initialized.",
90*795d594fSAndroid Build Coastguard Worker                         klass->PrettyTypeOf().c_str());
91*795d594fSAndroid Build Coastguard Worker       return false;
92*795d594fSAndroid Build Coastguard Worker     }
93*795d594fSAndroid Build Coastguard Worker   }
94*795d594fSAndroid Build Coastguard Worker 
95*795d594fSAndroid Build Coastguard Worker   if (strict_mode) {
96*795d594fSAndroid Build Coastguard Worker     EnterTransactionMode(/*strict=*/ true, klass.Get());
97*795d594fSAndroid Build Coastguard Worker   }
98*795d594fSAndroid Build Coastguard Worker   bool success = ClassLinker::InitializeClass(self, klass, can_init_statics, can_init_parents);
99*795d594fSAndroid Build Coastguard Worker 
100*795d594fSAndroid Build Coastguard Worker   if (strict_mode) {
101*795d594fSAndroid Build Coastguard Worker     if (success) {
102*795d594fSAndroid Build Coastguard Worker       // Exit Transaction if success.
103*795d594fSAndroid Build Coastguard Worker       ExitTransactionMode();
104*795d594fSAndroid Build Coastguard Worker     } else {
105*795d594fSAndroid Build Coastguard Worker       // If not successfully initialized, don't rollback immediately, leave the cleanup to compiler
106*795d594fSAndroid Build Coastguard Worker       // driver which needs abort message and exception.
107*795d594fSAndroid Build Coastguard Worker       DCHECK(self->IsExceptionPending());
108*795d594fSAndroid Build Coastguard Worker     }
109*795d594fSAndroid Build Coastguard Worker   }
110*795d594fSAndroid Build Coastguard Worker   return success;
111*795d594fSAndroid Build Coastguard Worker }
112*795d594fSAndroid Build Coastguard Worker 
PerformClassVerification(Thread * self,verifier::VerifierDeps * verifier_deps,Handle<mirror::Class> klass,verifier::HardFailLogMode log_level,std::string * error_msg)113*795d594fSAndroid Build Coastguard Worker verifier::FailureKind AotClassLinker::PerformClassVerification(
114*795d594fSAndroid Build Coastguard Worker     Thread* self,
115*795d594fSAndroid Build Coastguard Worker     verifier::VerifierDeps* verifier_deps,
116*795d594fSAndroid Build Coastguard Worker     Handle<mirror::Class> klass,
117*795d594fSAndroid Build Coastguard Worker     verifier::HardFailLogMode log_level,
118*795d594fSAndroid Build Coastguard Worker     std::string* error_msg) {
119*795d594fSAndroid Build Coastguard Worker   Runtime* const runtime = Runtime::Current();
120*795d594fSAndroid Build Coastguard Worker   CompilerCallbacks* callbacks = runtime->GetCompilerCallbacks();
121*795d594fSAndroid Build Coastguard Worker   ClassStatus old_status = callbacks->GetPreviousClassState(
122*795d594fSAndroid Build Coastguard Worker       ClassReference(&klass->GetDexFile(), klass->GetDexClassDefIndex()));
123*795d594fSAndroid Build Coastguard Worker   // Was it verified? Report no failure.
124*795d594fSAndroid Build Coastguard Worker   if (old_status >= ClassStatus::kVerified) {
125*795d594fSAndroid Build Coastguard Worker     return verifier::FailureKind::kNoFailure;
126*795d594fSAndroid Build Coastguard Worker   }
127*795d594fSAndroid Build Coastguard Worker   if (old_status >= ClassStatus::kVerifiedNeedsAccessChecks) {
128*795d594fSAndroid Build Coastguard Worker     return verifier::FailureKind::kAccessChecksFailure;
129*795d594fSAndroid Build Coastguard Worker   }
130*795d594fSAndroid Build Coastguard Worker   // Does it need to be verified at runtime? Report soft failure.
131*795d594fSAndroid Build Coastguard Worker   if (old_status >= ClassStatus::kRetryVerificationAtRuntime) {
132*795d594fSAndroid Build Coastguard Worker     // Error messages from here are only reported through -verbose:class. It is not worth it to
133*795d594fSAndroid Build Coastguard Worker     // create a message.
134*795d594fSAndroid Build Coastguard Worker     return verifier::FailureKind::kSoftFailure;
135*795d594fSAndroid Build Coastguard Worker   }
136*795d594fSAndroid Build Coastguard Worker   // Do the actual work.
137*795d594fSAndroid Build Coastguard Worker   return ClassLinker::PerformClassVerification(self, verifier_deps, klass, log_level, error_msg);
138*795d594fSAndroid Build Coastguard Worker }
139*795d594fSAndroid Build Coastguard Worker 
140*795d594fSAndroid Build Coastguard Worker static const std::vector<const DexFile*>* gAppImageDexFiles = nullptr;
141*795d594fSAndroid Build Coastguard Worker 
SetAppImageDexFiles(const std::vector<const DexFile * > * app_image_dex_files)142*795d594fSAndroid Build Coastguard Worker void AotClassLinker::SetAppImageDexFiles(const std::vector<const DexFile*>* app_image_dex_files) {
143*795d594fSAndroid Build Coastguard Worker   gAppImageDexFiles = app_image_dex_files;
144*795d594fSAndroid Build Coastguard Worker }
145*795d594fSAndroid Build Coastguard Worker 
CanReferenceInBootImageExtensionOrAppImage(ObjPtr<mirror::Class> klass,gc::Heap * heap)146*795d594fSAndroid Build Coastguard Worker bool AotClassLinker::CanReferenceInBootImageExtensionOrAppImage(
147*795d594fSAndroid Build Coastguard Worker     ObjPtr<mirror::Class> klass, gc::Heap* heap) {
148*795d594fSAndroid Build Coastguard Worker   // Do not allow referencing a class or instance of a class defined in a dex file
149*795d594fSAndroid Build Coastguard Worker   // belonging to the boot image we're compiling against but not itself in the boot image;
150*795d594fSAndroid Build Coastguard Worker   // or a class referencing such classes as component type, superclass or interface.
151*795d594fSAndroid Build Coastguard Worker   // Allowing this could yield duplicate class objects from multiple images.
152*795d594fSAndroid Build Coastguard Worker 
153*795d594fSAndroid Build Coastguard Worker   if (heap->ObjectIsInBootImageSpace(klass)) {
154*795d594fSAndroid Build Coastguard Worker     return true;  // Already included in the boot image we're compiling against.
155*795d594fSAndroid Build Coastguard Worker   }
156*795d594fSAndroid Build Coastguard Worker 
157*795d594fSAndroid Build Coastguard Worker   // Treat arrays and primitive types specially because they do not have a DexCache that we
158*795d594fSAndroid Build Coastguard Worker   // can use to check whether the dex file belongs to the boot image we're compiling against.
159*795d594fSAndroid Build Coastguard Worker   DCHECK(!klass->IsPrimitive());  // Primitive classes must be in the primary boot image.
160*795d594fSAndroid Build Coastguard Worker   if (klass->IsArrayClass()) {
161*795d594fSAndroid Build Coastguard Worker     DCHECK(heap->ObjectIsInBootImageSpace(klass->GetIfTable()));  // IfTable is OK.
162*795d594fSAndroid Build Coastguard Worker     // Arrays of all dimensions are tied to the dex file of the non-array component type.
163*795d594fSAndroid Build Coastguard Worker     do {
164*795d594fSAndroid Build Coastguard Worker       klass = klass->GetComponentType();
165*795d594fSAndroid Build Coastguard Worker     } while (klass->IsArrayClass());
166*795d594fSAndroid Build Coastguard Worker     if (klass->IsPrimitive()) {
167*795d594fSAndroid Build Coastguard Worker       return false;
168*795d594fSAndroid Build Coastguard Worker     }
169*795d594fSAndroid Build Coastguard Worker     // Do not allow arrays of erroneous classes (the array class is not itself erroneous).
170*795d594fSAndroid Build Coastguard Worker     if (klass->IsErroneous()) {
171*795d594fSAndroid Build Coastguard Worker       return false;
172*795d594fSAndroid Build Coastguard Worker     }
173*795d594fSAndroid Build Coastguard Worker   }
174*795d594fSAndroid Build Coastguard Worker 
175*795d594fSAndroid Build Coastguard Worker   auto can_reference_dex_cache = [&](ObjPtr<mirror::DexCache> dex_cache)
176*795d594fSAndroid Build Coastguard Worker       REQUIRES_SHARED(Locks::mutator_lock_) {
177*795d594fSAndroid Build Coastguard Worker     // We cannot reference a boot image dex cache for classes
178*795d594fSAndroid Build Coastguard Worker     // that were not themselves in the boot image.
179*795d594fSAndroid Build Coastguard Worker     if (heap->ObjectIsInBootImageSpace(dex_cache)) {
180*795d594fSAndroid Build Coastguard Worker       return false;
181*795d594fSAndroid Build Coastguard Worker     }
182*795d594fSAndroid Build Coastguard Worker     // App image compilation can pull in dex files from parent or library class loaders.
183*795d594fSAndroid Build Coastguard Worker     // Classes from such dex files cannot be included or referenced in the current app image
184*795d594fSAndroid Build Coastguard Worker     // to avoid conflicts with classes in the parent or library class loader's app image.
185*795d594fSAndroid Build Coastguard Worker     if (gAppImageDexFiles != nullptr &&
186*795d594fSAndroid Build Coastguard Worker         !ContainsElement(*gAppImageDexFiles, dex_cache->GetDexFile())) {
187*795d594fSAndroid Build Coastguard Worker       return false;
188*795d594fSAndroid Build Coastguard Worker     }
189*795d594fSAndroid Build Coastguard Worker     return true;
190*795d594fSAndroid Build Coastguard Worker   };
191*795d594fSAndroid Build Coastguard Worker 
192*795d594fSAndroid Build Coastguard Worker   // Check the class itself.
193*795d594fSAndroid Build Coastguard Worker   if (!can_reference_dex_cache(klass->GetDexCache())) {
194*795d594fSAndroid Build Coastguard Worker     return false;
195*795d594fSAndroid Build Coastguard Worker   }
196*795d594fSAndroid Build Coastguard Worker 
197*795d594fSAndroid Build Coastguard Worker   // Check superclasses.
198*795d594fSAndroid Build Coastguard Worker   ObjPtr<mirror::Class> superclass = klass->GetSuperClass();
199*795d594fSAndroid Build Coastguard Worker   while (!heap->ObjectIsInBootImageSpace(superclass)) {
200*795d594fSAndroid Build Coastguard Worker     DCHECK(superclass != nullptr);  // Cannot skip Object which is in the primary boot image.
201*795d594fSAndroid Build Coastguard Worker     if (!can_reference_dex_cache(superclass->GetDexCache())) {
202*795d594fSAndroid Build Coastguard Worker       return false;
203*795d594fSAndroid Build Coastguard Worker     }
204*795d594fSAndroid Build Coastguard Worker     superclass = superclass->GetSuperClass();
205*795d594fSAndroid Build Coastguard Worker   }
206*795d594fSAndroid Build Coastguard Worker 
207*795d594fSAndroid Build Coastguard Worker   // Check IfTable. This includes direct and indirect interfaces.
208*795d594fSAndroid Build Coastguard Worker   ObjPtr<mirror::IfTable> if_table = klass->GetIfTable();
209*795d594fSAndroid Build Coastguard Worker   for (size_t i = 0, num_interfaces = klass->GetIfTableCount(); i < num_interfaces; ++i) {
210*795d594fSAndroid Build Coastguard Worker     ObjPtr<mirror::Class> interface = if_table->GetInterface(i);
211*795d594fSAndroid Build Coastguard Worker     DCHECK(interface != nullptr);
212*795d594fSAndroid Build Coastguard Worker     if (!heap->ObjectIsInBootImageSpace(interface) &&
213*795d594fSAndroid Build Coastguard Worker         !can_reference_dex_cache(interface->GetDexCache())) {
214*795d594fSAndroid Build Coastguard Worker       return false;
215*795d594fSAndroid Build Coastguard Worker     }
216*795d594fSAndroid Build Coastguard Worker   }
217*795d594fSAndroid Build Coastguard Worker 
218*795d594fSAndroid Build Coastguard Worker   if (kIsDebugBuild) {
219*795d594fSAndroid Build Coastguard Worker     // All virtual methods must come from classes we have already checked above.
220*795d594fSAndroid Build Coastguard Worker     PointerSize pointer_size = Runtime::Current()->GetClassLinker()->GetImagePointerSize();
221*795d594fSAndroid Build Coastguard Worker     ObjPtr<mirror::Class> k = klass;
222*795d594fSAndroid Build Coastguard Worker     while (!heap->ObjectIsInBootImageSpace(k)) {
223*795d594fSAndroid Build Coastguard Worker       for (auto& m : k->GetVirtualMethods(pointer_size)) {
224*795d594fSAndroid Build Coastguard Worker         ObjPtr<mirror::Class> declaring_class = m.GetDeclaringClass();
225*795d594fSAndroid Build Coastguard Worker         CHECK(heap->ObjectIsInBootImageSpace(declaring_class) ||
226*795d594fSAndroid Build Coastguard Worker               can_reference_dex_cache(declaring_class->GetDexCache()));
227*795d594fSAndroid Build Coastguard Worker       }
228*795d594fSAndroid Build Coastguard Worker       k = k->GetSuperClass();
229*795d594fSAndroid Build Coastguard Worker     }
230*795d594fSAndroid Build Coastguard Worker   }
231*795d594fSAndroid Build Coastguard Worker 
232*795d594fSAndroid Build Coastguard Worker   return true;
233*795d594fSAndroid Build Coastguard Worker }
234*795d594fSAndroid Build Coastguard Worker 
SetSdkChecker(std::unique_ptr<SdkChecker> && sdk_checker)235*795d594fSAndroid Build Coastguard Worker void AotClassLinker::SetSdkChecker(std::unique_ptr<SdkChecker>&& sdk_checker) {
236*795d594fSAndroid Build Coastguard Worker   sdk_checker_ = std::move(sdk_checker);
237*795d594fSAndroid Build Coastguard Worker }
238*795d594fSAndroid Build Coastguard Worker 
GetSdkChecker() const239*795d594fSAndroid Build Coastguard Worker const SdkChecker* AotClassLinker::GetSdkChecker() const {
240*795d594fSAndroid Build Coastguard Worker   return sdk_checker_.get();
241*795d594fSAndroid Build Coastguard Worker }
242*795d594fSAndroid Build Coastguard Worker 
DenyAccessBasedOnPublicSdk(ArtMethod * art_method) const243*795d594fSAndroid Build Coastguard Worker bool AotClassLinker::DenyAccessBasedOnPublicSdk(ArtMethod* art_method) const {
244*795d594fSAndroid Build Coastguard Worker   return sdk_checker_ != nullptr && sdk_checker_->ShouldDenyAccess(art_method);
245*795d594fSAndroid Build Coastguard Worker }
DenyAccessBasedOnPublicSdk(ArtField * art_field) const246*795d594fSAndroid Build Coastguard Worker bool AotClassLinker::DenyAccessBasedOnPublicSdk(ArtField* art_field) const {
247*795d594fSAndroid Build Coastguard Worker   return sdk_checker_ != nullptr && sdk_checker_->ShouldDenyAccess(art_field);
248*795d594fSAndroid Build Coastguard Worker }
DenyAccessBasedOnPublicSdk(std::string_view type_descriptor) const249*795d594fSAndroid Build Coastguard Worker bool AotClassLinker::DenyAccessBasedOnPublicSdk(std::string_view type_descriptor) const {
250*795d594fSAndroid Build Coastguard Worker   return sdk_checker_ != nullptr && sdk_checker_->ShouldDenyAccess(type_descriptor);
251*795d594fSAndroid Build Coastguard Worker }
252*795d594fSAndroid Build Coastguard Worker 
SetEnablePublicSdkChecks(bool enabled)253*795d594fSAndroid Build Coastguard Worker void AotClassLinker::SetEnablePublicSdkChecks(bool enabled) {
254*795d594fSAndroid Build Coastguard Worker   if (sdk_checker_ != nullptr) {
255*795d594fSAndroid Build Coastguard Worker     sdk_checker_->SetEnabled(enabled);
256*795d594fSAndroid Build Coastguard Worker   }
257*795d594fSAndroid Build Coastguard Worker }
258*795d594fSAndroid Build Coastguard Worker 
259*795d594fSAndroid Build Coastguard Worker // Transaction support.
260*795d594fSAndroid Build Coastguard Worker 
IsActiveTransaction() const261*795d594fSAndroid Build Coastguard Worker bool AotClassLinker::IsActiveTransaction() const {
262*795d594fSAndroid Build Coastguard Worker   bool result = Runtime::Current()->IsActiveTransaction();
263*795d594fSAndroid Build Coastguard Worker   DCHECK_EQ(result, !preinitialization_transactions_.empty() && !GetTransaction()->IsRollingBack());
264*795d594fSAndroid Build Coastguard Worker   return result;
265*795d594fSAndroid Build Coastguard Worker }
266*795d594fSAndroid Build Coastguard Worker 
EnterTransactionMode(bool strict,mirror::Class * root)267*795d594fSAndroid Build Coastguard Worker void AotClassLinker::EnterTransactionMode(bool strict, mirror::Class* root) {
268*795d594fSAndroid Build Coastguard Worker   Runtime* runtime = Runtime::Current();
269*795d594fSAndroid Build Coastguard Worker   ArenaPool* arena_pool = nullptr;
270*795d594fSAndroid Build Coastguard Worker   ArenaStack* arena_stack = nullptr;
271*795d594fSAndroid Build Coastguard Worker   if (preinitialization_transactions_.empty()) {  // Top-level transaction?
272*795d594fSAndroid Build Coastguard Worker     // Make initialized classes visibly initialized now. If that happened during the transaction
273*795d594fSAndroid Build Coastguard Worker     // and then the transaction was aborted, we would roll back the status update but not the
274*795d594fSAndroid Build Coastguard Worker     // ClassLinker's bookkeeping structures, so these classes would never be visibly initialized.
275*795d594fSAndroid Build Coastguard Worker     {
276*795d594fSAndroid Build Coastguard Worker       Thread* self = Thread::Current();
277*795d594fSAndroid Build Coastguard Worker       StackHandleScope<1> hs(self);
278*795d594fSAndroid Build Coastguard Worker       HandleWrapper<mirror::Class> h(hs.NewHandleWrapper(&root));
279*795d594fSAndroid Build Coastguard Worker       ScopedThreadSuspension sts(self, ThreadState::kNative);
280*795d594fSAndroid Build Coastguard Worker       MakeInitializedClassesVisiblyInitialized(Thread::Current(), /*wait=*/ true);
281*795d594fSAndroid Build Coastguard Worker     }
282*795d594fSAndroid Build Coastguard Worker     // Pass the runtime `ArenaPool` to the transaction.
283*795d594fSAndroid Build Coastguard Worker     arena_pool = runtime->GetArenaPool();
284*795d594fSAndroid Build Coastguard Worker   } else {
285*795d594fSAndroid Build Coastguard Worker     // Pass the `ArenaStack` from previous transaction to the new one.
286*795d594fSAndroid Build Coastguard Worker     arena_stack = preinitialization_transactions_.front().GetArenaStack();
287*795d594fSAndroid Build Coastguard Worker   }
288*795d594fSAndroid Build Coastguard Worker   preinitialization_transactions_.emplace_front(strict, root, arena_stack, arena_pool);
289*795d594fSAndroid Build Coastguard Worker   runtime->SetActiveTransaction();
290*795d594fSAndroid Build Coastguard Worker }
291*795d594fSAndroid Build Coastguard Worker 
ExitTransactionMode()292*795d594fSAndroid Build Coastguard Worker void AotClassLinker::ExitTransactionMode() {
293*795d594fSAndroid Build Coastguard Worker   DCHECK(IsActiveTransaction());
294*795d594fSAndroid Build Coastguard Worker   preinitialization_transactions_.pop_front();
295*795d594fSAndroid Build Coastguard Worker   if (preinitialization_transactions_.empty()) {
296*795d594fSAndroid Build Coastguard Worker     Runtime::Current()->ClearActiveTransaction();
297*795d594fSAndroid Build Coastguard Worker   } else {
298*795d594fSAndroid Build Coastguard Worker     DCHECK(IsActiveTransaction());  // Trigger the DCHECK() in `IsActiveTransaction()`.
299*795d594fSAndroid Build Coastguard Worker   }
300*795d594fSAndroid Build Coastguard Worker }
301*795d594fSAndroid Build Coastguard Worker 
RollbackAllTransactions()302*795d594fSAndroid Build Coastguard Worker void AotClassLinker::RollbackAllTransactions() {
303*795d594fSAndroid Build Coastguard Worker   // If transaction is aborted, all transactions will be kept in the list.
304*795d594fSAndroid Build Coastguard Worker   // Rollback and exit all of them.
305*795d594fSAndroid Build Coastguard Worker   while (IsActiveTransaction()) {
306*795d594fSAndroid Build Coastguard Worker     RollbackAndExitTransactionMode();
307*795d594fSAndroid Build Coastguard Worker   }
308*795d594fSAndroid Build Coastguard Worker }
309*795d594fSAndroid Build Coastguard Worker 
RollbackAndExitTransactionMode()310*795d594fSAndroid Build Coastguard Worker void AotClassLinker::RollbackAndExitTransactionMode() {
311*795d594fSAndroid Build Coastguard Worker   DCHECK(IsActiveTransaction());
312*795d594fSAndroid Build Coastguard Worker   Runtime::Current()->ClearActiveTransaction();
313*795d594fSAndroid Build Coastguard Worker   preinitialization_transactions_.front().Rollback();
314*795d594fSAndroid Build Coastguard Worker   preinitialization_transactions_.pop_front();
315*795d594fSAndroid Build Coastguard Worker   if (!preinitialization_transactions_.empty()) {
316*795d594fSAndroid Build Coastguard Worker     Runtime::Current()->SetActiveTransaction();
317*795d594fSAndroid Build Coastguard Worker   }
318*795d594fSAndroid Build Coastguard Worker }
319*795d594fSAndroid Build Coastguard Worker 
GetTransaction() const320*795d594fSAndroid Build Coastguard Worker const Transaction* AotClassLinker::GetTransaction() const {
321*795d594fSAndroid Build Coastguard Worker   DCHECK(!preinitialization_transactions_.empty());
322*795d594fSAndroid Build Coastguard Worker   return &preinitialization_transactions_.front();
323*795d594fSAndroid Build Coastguard Worker }
324*795d594fSAndroid Build Coastguard Worker 
GetTransaction()325*795d594fSAndroid Build Coastguard Worker Transaction* AotClassLinker::GetTransaction() {
326*795d594fSAndroid Build Coastguard Worker   DCHECK(!preinitialization_transactions_.empty());
327*795d594fSAndroid Build Coastguard Worker   return &preinitialization_transactions_.front();
328*795d594fSAndroid Build Coastguard Worker }
329*795d594fSAndroid Build Coastguard Worker 
IsActiveStrictTransactionMode() const330*795d594fSAndroid Build Coastguard Worker bool AotClassLinker::IsActiveStrictTransactionMode() const {
331*795d594fSAndroid Build Coastguard Worker   return IsActiveTransaction() && GetTransaction()->IsStrict();
332*795d594fSAndroid Build Coastguard Worker }
333*795d594fSAndroid Build Coastguard Worker 
TransactionWriteConstraint(Thread * self,ObjPtr<mirror::Object> obj)334*795d594fSAndroid Build Coastguard Worker bool AotClassLinker::TransactionWriteConstraint(Thread* self, ObjPtr<mirror::Object> obj) {
335*795d594fSAndroid Build Coastguard Worker   DCHECK(IsActiveTransaction());
336*795d594fSAndroid Build Coastguard Worker   if (GetTransaction()->WriteConstraint(obj)) {
337*795d594fSAndroid Build Coastguard Worker     Runtime* runtime = Runtime::Current();
338*795d594fSAndroid Build Coastguard Worker     DCHECK(runtime->GetHeap()->ObjectIsInBootImageSpace(obj) || obj->IsClass());
339*795d594fSAndroid Build Coastguard Worker     const char* extra = runtime->GetHeap()->ObjectIsInBootImageSpace(obj) ? "boot image " : "";
340*795d594fSAndroid Build Coastguard Worker     AbortTransactionF(
341*795d594fSAndroid Build Coastguard Worker         self, "Can't set fields of %s%s", extra, obj->PrettyTypeOf().c_str());
342*795d594fSAndroid Build Coastguard Worker     return true;
343*795d594fSAndroid Build Coastguard Worker   }
344*795d594fSAndroid Build Coastguard Worker   return false;
345*795d594fSAndroid Build Coastguard Worker }
346*795d594fSAndroid Build Coastguard Worker 
TransactionWriteValueConstraint(Thread * self,ObjPtr<mirror::Object> value)347*795d594fSAndroid Build Coastguard Worker bool AotClassLinker::TransactionWriteValueConstraint(Thread* self, ObjPtr<mirror::Object> value) {
348*795d594fSAndroid Build Coastguard Worker   DCHECK(IsActiveTransaction());
349*795d594fSAndroid Build Coastguard Worker   if (GetTransaction()->WriteValueConstraint(value)) {
350*795d594fSAndroid Build Coastguard Worker     DCHECK(value != nullptr);
351*795d594fSAndroid Build Coastguard Worker     const char* description = value->IsClass() ? "class" : "instance of";
352*795d594fSAndroid Build Coastguard Worker     ObjPtr<mirror::Class> klass = value->IsClass() ? value->AsClass() : value->GetClass();
353*795d594fSAndroid Build Coastguard Worker     AbortTransactionF(
354*795d594fSAndroid Build Coastguard Worker         self, "Can't store reference to %s %s", description, klass->PrettyDescriptor().c_str());
355*795d594fSAndroid Build Coastguard Worker     return true;
356*795d594fSAndroid Build Coastguard Worker   }
357*795d594fSAndroid Build Coastguard Worker   return false;
358*795d594fSAndroid Build Coastguard Worker }
359*795d594fSAndroid Build Coastguard Worker 
TransactionReadConstraint(Thread * self,ObjPtr<mirror::Object> obj)360*795d594fSAndroid Build Coastguard Worker bool AotClassLinker::TransactionReadConstraint(Thread* self, ObjPtr<mirror::Object> obj) {
361*795d594fSAndroid Build Coastguard Worker   DCHECK(obj->IsClass());
362*795d594fSAndroid Build Coastguard Worker   if (GetTransaction()->ReadConstraint(obj)) {
363*795d594fSAndroid Build Coastguard Worker     AbortTransactionF(self,
364*795d594fSAndroid Build Coastguard Worker                       "Can't read static fields of %s since it does not belong to clinit's class.",
365*795d594fSAndroid Build Coastguard Worker                       obj->PrettyTypeOf().c_str());
366*795d594fSAndroid Build Coastguard Worker     return true;
367*795d594fSAndroid Build Coastguard Worker   }
368*795d594fSAndroid Build Coastguard Worker   return false;
369*795d594fSAndroid Build Coastguard Worker }
370*795d594fSAndroid Build Coastguard Worker 
TransactionAllocationConstraint(Thread * self,ObjPtr<mirror::Class> klass)371*795d594fSAndroid Build Coastguard Worker bool AotClassLinker::TransactionAllocationConstraint(Thread* self, ObjPtr<mirror::Class> klass) {
372*795d594fSAndroid Build Coastguard Worker   DCHECK(IsActiveTransaction());
373*795d594fSAndroid Build Coastguard Worker   if (klass->IsFinalizable()) {
374*795d594fSAndroid Build Coastguard Worker     AbortTransactionF(self,
375*795d594fSAndroid Build Coastguard Worker                       "Allocating finalizable object in transaction: %s",
376*795d594fSAndroid Build Coastguard Worker                       klass->PrettyDescriptor().c_str());
377*795d594fSAndroid Build Coastguard Worker     return true;
378*795d594fSAndroid Build Coastguard Worker   }
379*795d594fSAndroid Build Coastguard Worker   return false;
380*795d594fSAndroid Build Coastguard Worker }
381*795d594fSAndroid Build Coastguard Worker 
RecordWriteFieldBoolean(mirror::Object * obj,MemberOffset field_offset,uint8_t value,bool is_volatile)382*795d594fSAndroid Build Coastguard Worker void AotClassLinker::RecordWriteFieldBoolean(mirror::Object* obj,
383*795d594fSAndroid Build Coastguard Worker                                              MemberOffset field_offset,
384*795d594fSAndroid Build Coastguard Worker                                              uint8_t value,
385*795d594fSAndroid Build Coastguard Worker                                              bool is_volatile) {
386*795d594fSAndroid Build Coastguard Worker   DCHECK(IsActiveTransaction());
387*795d594fSAndroid Build Coastguard Worker   GetTransaction()->RecordWriteFieldBoolean(obj, field_offset, value, is_volatile);
388*795d594fSAndroid Build Coastguard Worker }
389*795d594fSAndroid Build Coastguard Worker 
RecordWriteFieldByte(mirror::Object * obj,MemberOffset field_offset,int8_t value,bool is_volatile)390*795d594fSAndroid Build Coastguard Worker void AotClassLinker::RecordWriteFieldByte(mirror::Object* obj,
391*795d594fSAndroid Build Coastguard Worker                                           MemberOffset field_offset,
392*795d594fSAndroid Build Coastguard Worker                                           int8_t value,
393*795d594fSAndroid Build Coastguard Worker                                           bool is_volatile) {
394*795d594fSAndroid Build Coastguard Worker   DCHECK(IsActiveTransaction());
395*795d594fSAndroid Build Coastguard Worker   GetTransaction()->RecordWriteFieldByte(obj, field_offset, value, is_volatile);
396*795d594fSAndroid Build Coastguard Worker }
397*795d594fSAndroid Build Coastguard Worker 
RecordWriteFieldChar(mirror::Object * obj,MemberOffset field_offset,uint16_t value,bool is_volatile)398*795d594fSAndroid Build Coastguard Worker void AotClassLinker::RecordWriteFieldChar(mirror::Object* obj,
399*795d594fSAndroid Build Coastguard Worker                                           MemberOffset field_offset,
400*795d594fSAndroid Build Coastguard Worker                                           uint16_t value,
401*795d594fSAndroid Build Coastguard Worker                                           bool is_volatile) {
402*795d594fSAndroid Build Coastguard Worker   DCHECK(IsActiveTransaction());
403*795d594fSAndroid Build Coastguard Worker   GetTransaction()->RecordWriteFieldChar(obj, field_offset, value, is_volatile);
404*795d594fSAndroid Build Coastguard Worker }
405*795d594fSAndroid Build Coastguard Worker 
RecordWriteFieldShort(mirror::Object * obj,MemberOffset field_offset,int16_t value,bool is_volatile)406*795d594fSAndroid Build Coastguard Worker void AotClassLinker::RecordWriteFieldShort(mirror::Object* obj,
407*795d594fSAndroid Build Coastguard Worker                                            MemberOffset field_offset,
408*795d594fSAndroid Build Coastguard Worker                                            int16_t value,
409*795d594fSAndroid Build Coastguard Worker                                            bool is_volatile) {
410*795d594fSAndroid Build Coastguard Worker   DCHECK(IsActiveTransaction());
411*795d594fSAndroid Build Coastguard Worker   GetTransaction()->RecordWriteFieldShort(obj, field_offset, value, is_volatile);
412*795d594fSAndroid Build Coastguard Worker }
413*795d594fSAndroid Build Coastguard Worker 
RecordWriteField32(mirror::Object * obj,MemberOffset field_offset,uint32_t value,bool is_volatile)414*795d594fSAndroid Build Coastguard Worker void AotClassLinker::RecordWriteField32(mirror::Object* obj,
415*795d594fSAndroid Build Coastguard Worker                                         MemberOffset field_offset,
416*795d594fSAndroid Build Coastguard Worker                                         uint32_t value,
417*795d594fSAndroid Build Coastguard Worker                                         bool is_volatile) {
418*795d594fSAndroid Build Coastguard Worker   DCHECK(IsActiveTransaction());
419*795d594fSAndroid Build Coastguard Worker   GetTransaction()->RecordWriteField32(obj, field_offset, value, is_volatile);
420*795d594fSAndroid Build Coastguard Worker }
421*795d594fSAndroid Build Coastguard Worker 
RecordWriteField64(mirror::Object * obj,MemberOffset field_offset,uint64_t value,bool is_volatile)422*795d594fSAndroid Build Coastguard Worker void AotClassLinker::RecordWriteField64(mirror::Object* obj,
423*795d594fSAndroid Build Coastguard Worker                                         MemberOffset field_offset,
424*795d594fSAndroid Build Coastguard Worker                                         uint64_t value,
425*795d594fSAndroid Build Coastguard Worker                                         bool is_volatile) {
426*795d594fSAndroid Build Coastguard Worker   DCHECK(IsActiveTransaction());
427*795d594fSAndroid Build Coastguard Worker   GetTransaction()->RecordWriteField64(obj, field_offset, value, is_volatile);
428*795d594fSAndroid Build Coastguard Worker }
429*795d594fSAndroid Build Coastguard Worker 
RecordWriteFieldReference(mirror::Object * obj,MemberOffset field_offset,ObjPtr<mirror::Object> value,bool is_volatile)430*795d594fSAndroid Build Coastguard Worker void AotClassLinker::RecordWriteFieldReference(mirror::Object* obj,
431*795d594fSAndroid Build Coastguard Worker                                                MemberOffset field_offset,
432*795d594fSAndroid Build Coastguard Worker                                                ObjPtr<mirror::Object> value,
433*795d594fSAndroid Build Coastguard Worker                                                bool is_volatile) {
434*795d594fSAndroid Build Coastguard Worker   DCHECK(IsActiveTransaction());
435*795d594fSAndroid Build Coastguard Worker   GetTransaction()->RecordWriteFieldReference(obj, field_offset, value.Ptr(), is_volatile);
436*795d594fSAndroid Build Coastguard Worker }
437*795d594fSAndroid Build Coastguard Worker 
RecordWriteArray(mirror::Array * array,size_t index,uint64_t value)438*795d594fSAndroid Build Coastguard Worker void AotClassLinker::RecordWriteArray(mirror::Array* array, size_t index, uint64_t value) {
439*795d594fSAndroid Build Coastguard Worker   DCHECK(IsActiveTransaction());
440*795d594fSAndroid Build Coastguard Worker   GetTransaction()->RecordWriteArray(array, index, value);
441*795d594fSAndroid Build Coastguard Worker }
442*795d594fSAndroid Build Coastguard Worker 
RecordStrongStringInsertion(ObjPtr<mirror::String> s)443*795d594fSAndroid Build Coastguard Worker void AotClassLinker::RecordStrongStringInsertion(ObjPtr<mirror::String> s) {
444*795d594fSAndroid Build Coastguard Worker   DCHECK(IsActiveTransaction());
445*795d594fSAndroid Build Coastguard Worker   GetTransaction()->RecordStrongStringInsertion(s);
446*795d594fSAndroid Build Coastguard Worker }
447*795d594fSAndroid Build Coastguard Worker 
RecordWeakStringInsertion(ObjPtr<mirror::String> s)448*795d594fSAndroid Build Coastguard Worker void AotClassLinker::RecordWeakStringInsertion(ObjPtr<mirror::String> s) {
449*795d594fSAndroid Build Coastguard Worker   DCHECK(IsActiveTransaction());
450*795d594fSAndroid Build Coastguard Worker   GetTransaction()->RecordWeakStringInsertion(s);
451*795d594fSAndroid Build Coastguard Worker }
452*795d594fSAndroid Build Coastguard Worker 
RecordStrongStringRemoval(ObjPtr<mirror::String> s)453*795d594fSAndroid Build Coastguard Worker void AotClassLinker::RecordStrongStringRemoval(ObjPtr<mirror::String> s) {
454*795d594fSAndroid Build Coastguard Worker   DCHECK(IsActiveTransaction());
455*795d594fSAndroid Build Coastguard Worker   GetTransaction()->RecordStrongStringRemoval(s);
456*795d594fSAndroid Build Coastguard Worker }
457*795d594fSAndroid Build Coastguard Worker 
RecordWeakStringRemoval(ObjPtr<mirror::String> s)458*795d594fSAndroid Build Coastguard Worker void AotClassLinker::RecordWeakStringRemoval(ObjPtr<mirror::String> s) {
459*795d594fSAndroid Build Coastguard Worker   DCHECK(IsActiveTransaction());
460*795d594fSAndroid Build Coastguard Worker   GetTransaction()->RecordWeakStringRemoval(s);
461*795d594fSAndroid Build Coastguard Worker }
462*795d594fSAndroid Build Coastguard Worker 
RecordResolveString(ObjPtr<mirror::DexCache> dex_cache,dex::StringIndex string_idx)463*795d594fSAndroid Build Coastguard Worker void AotClassLinker::RecordResolveString(ObjPtr<mirror::DexCache> dex_cache,
464*795d594fSAndroid Build Coastguard Worker                                          dex::StringIndex string_idx) {
465*795d594fSAndroid Build Coastguard Worker   DCHECK(IsActiveTransaction());
466*795d594fSAndroid Build Coastguard Worker   GetTransaction()->RecordResolveString(dex_cache, string_idx);
467*795d594fSAndroid Build Coastguard Worker }
468*795d594fSAndroid Build Coastguard Worker 
RecordResolveMethodType(ObjPtr<mirror::DexCache> dex_cache,dex::ProtoIndex proto_idx)469*795d594fSAndroid Build Coastguard Worker void AotClassLinker::RecordResolveMethodType(ObjPtr<mirror::DexCache> dex_cache,
470*795d594fSAndroid Build Coastguard Worker                                              dex::ProtoIndex proto_idx) {
471*795d594fSAndroid Build Coastguard Worker   DCHECK(IsActiveTransaction());
472*795d594fSAndroid Build Coastguard Worker   GetTransaction()->RecordResolveMethodType(dex_cache, proto_idx);
473*795d594fSAndroid Build Coastguard Worker }
474*795d594fSAndroid Build Coastguard Worker 
ThrowTransactionAbortError(Thread * self)475*795d594fSAndroid Build Coastguard Worker void AotClassLinker::ThrowTransactionAbortError(Thread* self) {
476*795d594fSAndroid Build Coastguard Worker   DCHECK(IsActiveTransaction());
477*795d594fSAndroid Build Coastguard Worker   // Passing nullptr means we rethrow an exception with the earlier transaction abort message.
478*795d594fSAndroid Build Coastguard Worker   GetTransaction()->ThrowAbortError(self, nullptr);
479*795d594fSAndroid Build Coastguard Worker }
480*795d594fSAndroid Build Coastguard Worker 
AbortTransactionF(Thread * self,const char * fmt,...)481*795d594fSAndroid Build Coastguard Worker void AotClassLinker::AbortTransactionF(Thread* self, const char* fmt, ...) {
482*795d594fSAndroid Build Coastguard Worker   va_list args;
483*795d594fSAndroid Build Coastguard Worker   va_start(args, fmt);
484*795d594fSAndroid Build Coastguard Worker   AbortTransactionV(self, fmt, args);
485*795d594fSAndroid Build Coastguard Worker   va_end(args);
486*795d594fSAndroid Build Coastguard Worker }
487*795d594fSAndroid Build Coastguard Worker 
AbortTransactionV(Thread * self,const char * fmt,va_list args)488*795d594fSAndroid Build Coastguard Worker void AotClassLinker::AbortTransactionV(Thread* self, const char* fmt, va_list args) {
489*795d594fSAndroid Build Coastguard Worker   CHECK(IsActiveTransaction());
490*795d594fSAndroid Build Coastguard Worker   // Constructs abort message.
491*795d594fSAndroid Build Coastguard Worker   std::string abort_message;
492*795d594fSAndroid Build Coastguard Worker   android::base::StringAppendV(&abort_message, fmt, args);
493*795d594fSAndroid Build Coastguard Worker   // Throws an exception so we can abort the transaction and rollback every change.
494*795d594fSAndroid Build Coastguard Worker   //
495*795d594fSAndroid Build Coastguard Worker   // Throwing an exception may cause its class initialization. If we mark the transaction
496*795d594fSAndroid Build Coastguard Worker   // aborted before that, we may warn with a false alarm. Throwing the exception before
497*795d594fSAndroid Build Coastguard Worker   // marking the transaction aborted avoids that.
498*795d594fSAndroid Build Coastguard Worker   // But now the transaction can be nested, and abort the transaction will relax the constraints
499*795d594fSAndroid Build Coastguard Worker   // for constructing stack trace.
500*795d594fSAndroid Build Coastguard Worker   GetTransaction()->Abort(abort_message);
501*795d594fSAndroid Build Coastguard Worker   GetTransaction()->ThrowAbortError(self, &abort_message);
502*795d594fSAndroid Build Coastguard Worker }
503*795d594fSAndroid Build Coastguard Worker 
IsTransactionAborted() const504*795d594fSAndroid Build Coastguard Worker bool AotClassLinker::IsTransactionAborted() const {
505*795d594fSAndroid Build Coastguard Worker   DCHECK(IsActiveTransaction());
506*795d594fSAndroid Build Coastguard Worker   return GetTransaction()->IsAborted();
507*795d594fSAndroid Build Coastguard Worker }
508*795d594fSAndroid Build Coastguard Worker 
VisitTransactionRoots(RootVisitor * visitor)509*795d594fSAndroid Build Coastguard Worker void AotClassLinker::VisitTransactionRoots(RootVisitor* visitor) {
510*795d594fSAndroid Build Coastguard Worker   for (Transaction& transaction : preinitialization_transactions_) {
511*795d594fSAndroid Build Coastguard Worker     transaction.VisitRoots(visitor);
512*795d594fSAndroid Build Coastguard Worker   }
513*795d594fSAndroid Build Coastguard Worker }
514*795d594fSAndroid Build Coastguard Worker 
GetTransactionalInterpreter()515*795d594fSAndroid Build Coastguard Worker const void* AotClassLinker::GetTransactionalInterpreter() {
516*795d594fSAndroid Build Coastguard Worker   return reinterpret_cast<const void*>(
517*795d594fSAndroid Build Coastguard Worker       &interpreter::ExecuteSwitchImplCpp</*transaction_active=*/ true>);
518*795d594fSAndroid Build Coastguard Worker }
519*795d594fSAndroid Build Coastguard Worker 
520*795d594fSAndroid Build Coastguard Worker }  // namespace art
521