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