xref: /aosp_15_r20/art/dex2oat/interpreter/unstarted_runtime_transaction_test.cc (revision 795d594fd825385562da6b089ea9b2033f3abf5a)
1*795d594fSAndroid Build Coastguard Worker /*
2*795d594fSAndroid Build Coastguard Worker  * Copyright (C) 2024 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 "interpreter/unstarted_runtime_test.h"
18*795d594fSAndroid Build Coastguard Worker 
19*795d594fSAndroid Build Coastguard Worker #include "class_root-inl.h"
20*795d594fSAndroid Build Coastguard Worker #include "common_transaction_test.h"
21*795d594fSAndroid Build Coastguard Worker #include "dex/descriptors_names.h"
22*795d594fSAndroid Build Coastguard Worker #include "interpreter/interpreter_common.h"
23*795d594fSAndroid Build Coastguard Worker #include "handle.h"
24*795d594fSAndroid Build Coastguard Worker #include "handle_scope-inl.h"
25*795d594fSAndroid Build Coastguard Worker #include "mirror/class-inl.h"
26*795d594fSAndroid Build Coastguard Worker 
27*795d594fSAndroid Build Coastguard Worker namespace art HIDDEN {
28*795d594fSAndroid Build Coastguard Worker namespace interpreter {
29*795d594fSAndroid Build Coastguard Worker 
30*795d594fSAndroid Build Coastguard Worker class UnstartedRuntimeTransactionTest : public CommonTransactionTestBase<UnstartedRuntimeTestBase> {
31*795d594fSAndroid Build Coastguard Worker  protected:
32*795d594fSAndroid Build Coastguard Worker   // Prepare for aborts. Aborts assume that the exception class is already resolved, as the
33*795d594fSAndroid Build Coastguard Worker   // loading code doesn't work under transactions.
PrepareForAborts()34*795d594fSAndroid Build Coastguard Worker   void PrepareForAborts() REQUIRES_SHARED(Locks::mutator_lock_) {
35*795d594fSAndroid Build Coastguard Worker     ObjPtr<mirror::Object> result =
36*795d594fSAndroid Build Coastguard Worker         FindClass(kTransactionAbortErrorDescriptor, ScopedNullHandle<mirror::ClassLoader>());
37*795d594fSAndroid Build Coastguard Worker     CHECK(result != nullptr);
38*795d594fSAndroid Build Coastguard Worker   }
39*795d594fSAndroid Build Coastguard Worker };
40*795d594fSAndroid Build Coastguard Worker 
TEST_F(UnstartedRuntimeTransactionTest,ToLowerUpper)41*795d594fSAndroid Build Coastguard Worker TEST_F(UnstartedRuntimeTransactionTest, ToLowerUpper) {
42*795d594fSAndroid Build Coastguard Worker   Thread* self = Thread::Current();
43*795d594fSAndroid Build Coastguard Worker   ScopedObjectAccess soa(self);
44*795d594fSAndroid Build Coastguard Worker   UniqueDeoptShadowFramePtr tmp = CreateShadowFrame(10, nullptr, 0);
45*795d594fSAndroid Build Coastguard Worker 
46*795d594fSAndroid Build Coastguard Worker   PrepareForAborts();
47*795d594fSAndroid Build Coastguard Worker 
48*795d594fSAndroid Build Coastguard Worker   for (uint32_t i = 128; i < 256; ++i) {
49*795d594fSAndroid Build Coastguard Worker     {
50*795d594fSAndroid Build Coastguard Worker       JValue result;
51*795d594fSAndroid Build Coastguard Worker       tmp->SetVReg(0, static_cast<int32_t>(i));
52*795d594fSAndroid Build Coastguard Worker       EnterTransactionMode();
53*795d594fSAndroid Build Coastguard Worker       UnstartedCharacterToLowerCase(self, tmp.get(), &result, 0);
54*795d594fSAndroid Build Coastguard Worker       ASSERT_TRUE(IsTransactionAborted());
55*795d594fSAndroid Build Coastguard Worker       ExitTransactionMode();
56*795d594fSAndroid Build Coastguard Worker       ASSERT_TRUE(self->IsExceptionPending());
57*795d594fSAndroid Build Coastguard Worker     }
58*795d594fSAndroid Build Coastguard Worker     {
59*795d594fSAndroid Build Coastguard Worker       JValue result;
60*795d594fSAndroid Build Coastguard Worker       tmp->SetVReg(0, static_cast<int32_t>(i));
61*795d594fSAndroid Build Coastguard Worker       EnterTransactionMode();
62*795d594fSAndroid Build Coastguard Worker       UnstartedCharacterToUpperCase(self, tmp.get(), &result, 0);
63*795d594fSAndroid Build Coastguard Worker       ASSERT_TRUE(IsTransactionAborted());
64*795d594fSAndroid Build Coastguard Worker       ExitTransactionMode();
65*795d594fSAndroid Build Coastguard Worker       ASSERT_TRUE(self->IsExceptionPending());
66*795d594fSAndroid Build Coastguard Worker     }
67*795d594fSAndroid Build Coastguard Worker   }
68*795d594fSAndroid Build Coastguard Worker   for (uint64_t i = 256; i <= std::numeric_limits<uint32_t>::max(); i <<= 1) {
69*795d594fSAndroid Build Coastguard Worker     {
70*795d594fSAndroid Build Coastguard Worker       JValue result;
71*795d594fSAndroid Build Coastguard Worker       tmp->SetVReg(0, static_cast<int32_t>(i));
72*795d594fSAndroid Build Coastguard Worker       EnterTransactionMode();
73*795d594fSAndroid Build Coastguard Worker       UnstartedCharacterToLowerCase(self, tmp.get(), &result, 0);
74*795d594fSAndroid Build Coastguard Worker       ASSERT_TRUE(IsTransactionAborted());
75*795d594fSAndroid Build Coastguard Worker       ExitTransactionMode();
76*795d594fSAndroid Build Coastguard Worker       ASSERT_TRUE(self->IsExceptionPending());
77*795d594fSAndroid Build Coastguard Worker     }
78*795d594fSAndroid Build Coastguard Worker     {
79*795d594fSAndroid Build Coastguard Worker       JValue result;
80*795d594fSAndroid Build Coastguard Worker       tmp->SetVReg(0, static_cast<int32_t>(i));
81*795d594fSAndroid Build Coastguard Worker       EnterTransactionMode();
82*795d594fSAndroid Build Coastguard Worker       UnstartedCharacterToUpperCase(self, tmp.get(), &result, 0);
83*795d594fSAndroid Build Coastguard Worker       ASSERT_TRUE(IsTransactionAborted());
84*795d594fSAndroid Build Coastguard Worker       ExitTransactionMode();
85*795d594fSAndroid Build Coastguard Worker       ASSERT_TRUE(self->IsExceptionPending());
86*795d594fSAndroid Build Coastguard Worker     }
87*795d594fSAndroid Build Coastguard Worker   }
88*795d594fSAndroid Build Coastguard Worker }
89*795d594fSAndroid Build Coastguard Worker 
TEST_F(UnstartedRuntimeTransactionTest,ThreadLocalGet)90*795d594fSAndroid Build Coastguard Worker TEST_F(UnstartedRuntimeTransactionTest, ThreadLocalGet) {
91*795d594fSAndroid Build Coastguard Worker   Thread* self = Thread::Current();
92*795d594fSAndroid Build Coastguard Worker   ScopedObjectAccess soa(self);
93*795d594fSAndroid Build Coastguard Worker   UniqueDeoptShadowFramePtr shadow_frame = CreateShadowFrame(10, nullptr, 0);
94*795d594fSAndroid Build Coastguard Worker 
95*795d594fSAndroid Build Coastguard Worker   // Negative test.
96*795d594fSAndroid Build Coastguard Worker   PrepareForAborts();
97*795d594fSAndroid Build Coastguard Worker 
98*795d594fSAndroid Build Coastguard Worker   // Just use a method in Class.
99*795d594fSAndroid Build Coastguard Worker   ObjPtr<mirror::Class> class_class = GetClassRoot<mirror::Class>();
100*795d594fSAndroid Build Coastguard Worker   ArtMethod* caller_method =
101*795d594fSAndroid Build Coastguard Worker       &*class_class->GetDeclaredMethods(class_linker_->GetImagePointerSize()).begin();
102*795d594fSAndroid Build Coastguard Worker   UniqueDeoptShadowFramePtr caller_frame = CreateShadowFrame(10, caller_method, 0);
103*795d594fSAndroid Build Coastguard Worker   shadow_frame->SetLink(caller_frame.get());
104*795d594fSAndroid Build Coastguard Worker 
105*795d594fSAndroid Build Coastguard Worker   JValue result;
106*795d594fSAndroid Build Coastguard Worker   EnterTransactionMode();
107*795d594fSAndroid Build Coastguard Worker   UnstartedThreadLocalGet(self, shadow_frame.get(), &result, 0);
108*795d594fSAndroid Build Coastguard Worker   ASSERT_TRUE(IsTransactionAborted());
109*795d594fSAndroid Build Coastguard Worker   ExitTransactionMode();
110*795d594fSAndroid Build Coastguard Worker   ASSERT_TRUE(self->IsExceptionPending());
111*795d594fSAndroid Build Coastguard Worker   self->ClearException();
112*795d594fSAndroid Build Coastguard Worker 
113*795d594fSAndroid Build Coastguard Worker   shadow_frame->ClearLink();
114*795d594fSAndroid Build Coastguard Worker }
115*795d594fSAndroid Build Coastguard Worker 
TEST_F(UnstartedRuntimeTransactionTest,ThreadCurrentThread)116*795d594fSAndroid Build Coastguard Worker TEST_F(UnstartedRuntimeTransactionTest, ThreadCurrentThread) {
117*795d594fSAndroid Build Coastguard Worker   Thread* self = Thread::Current();
118*795d594fSAndroid Build Coastguard Worker   ScopedObjectAccess soa(self);
119*795d594fSAndroid Build Coastguard Worker   UniqueDeoptShadowFramePtr shadow_frame = CreateShadowFrame(10, nullptr, 0);
120*795d594fSAndroid Build Coastguard Worker 
121*795d594fSAndroid Build Coastguard Worker   // Negative test. In general, currentThread should fail (as we should not leak a peer that will
122*795d594fSAndroid Build Coastguard Worker   // be recreated at runtime).
123*795d594fSAndroid Build Coastguard Worker   PrepareForAborts();
124*795d594fSAndroid Build Coastguard Worker 
125*795d594fSAndroid Build Coastguard Worker   JValue result;
126*795d594fSAndroid Build Coastguard Worker   EnterTransactionMode();
127*795d594fSAndroid Build Coastguard Worker   UnstartedThreadCurrentThread(self, shadow_frame.get(), &result, 0);
128*795d594fSAndroid Build Coastguard Worker   ASSERT_TRUE(IsTransactionAborted());
129*795d594fSAndroid Build Coastguard Worker   ExitTransactionMode();
130*795d594fSAndroid Build Coastguard Worker   ASSERT_TRUE(self->IsExceptionPending());
131*795d594fSAndroid Build Coastguard Worker   self->ClearException();
132*795d594fSAndroid Build Coastguard Worker }
133*795d594fSAndroid Build Coastguard Worker 
134*795d594fSAndroid Build Coastguard Worker class UnstartedClassForNameTransactionTest : public UnstartedRuntimeTransactionTest {
135*795d594fSAndroid Build Coastguard Worker  public:
136*795d594fSAndroid Build Coastguard Worker   template <typename T>
RunTest(T && runner,bool should_succeed)137*795d594fSAndroid Build Coastguard Worker   void RunTest(T&& runner, bool should_succeed) {
138*795d594fSAndroid Build Coastguard Worker     Thread* self = Thread::Current();
139*795d594fSAndroid Build Coastguard Worker     ScopedObjectAccess soa(self);
140*795d594fSAndroid Build Coastguard Worker 
141*795d594fSAndroid Build Coastguard Worker     // Ensure that Class is initialized.
142*795d594fSAndroid Build Coastguard Worker     CHECK(GetClassRoot<mirror::Class>()->IsInitialized());
143*795d594fSAndroid Build Coastguard Worker 
144*795d594fSAndroid Build Coastguard Worker     // A selection of classes from different core classpath components.
145*795d594fSAndroid Build Coastguard Worker     constexpr const char* kTestCases[] = {
146*795d594fSAndroid Build Coastguard Worker         "java.net.CookieManager",  // From libcore.
147*795d594fSAndroid Build Coastguard Worker         "dalvik.system.ClassExt",  // From libart.
148*795d594fSAndroid Build Coastguard Worker     };
149*795d594fSAndroid Build Coastguard Worker 
150*795d594fSAndroid Build Coastguard Worker     // For transaction mode, we cannot load any classes, as the pre-fence initialization of
151*795d594fSAndroid Build Coastguard Worker     // classes isn't transactional. Load them ahead of time.
152*795d594fSAndroid Build Coastguard Worker     for (const char* name : kTestCases) {
153*795d594fSAndroid Build Coastguard Worker       FindClass(DotToDescriptor(name).c_str(), ScopedNullHandle<mirror::ClassLoader>());
154*795d594fSAndroid Build Coastguard Worker       CHECK(!self->IsExceptionPending()) << self->GetException()->Dump();
155*795d594fSAndroid Build Coastguard Worker     }
156*795d594fSAndroid Build Coastguard Worker 
157*795d594fSAndroid Build Coastguard Worker     if (!should_succeed) {
158*795d594fSAndroid Build Coastguard Worker       // Negative test. In general, currentThread should fail (as we should not leak a peer that will
159*795d594fSAndroid Build Coastguard Worker       // be recreated at runtime).
160*795d594fSAndroid Build Coastguard Worker       PrepareForAborts();
161*795d594fSAndroid Build Coastguard Worker     }
162*795d594fSAndroid Build Coastguard Worker 
163*795d594fSAndroid Build Coastguard Worker     JValue result;
164*795d594fSAndroid Build Coastguard Worker     UniqueDeoptShadowFramePtr shadow_frame = CreateShadowFrame(10, nullptr, 0);
165*795d594fSAndroid Build Coastguard Worker 
166*795d594fSAndroid Build Coastguard Worker     for (const char* name : kTestCases) {
167*795d594fSAndroid Build Coastguard Worker       EnterTransactionMode();
168*795d594fSAndroid Build Coastguard Worker 
169*795d594fSAndroid Build Coastguard Worker       ObjPtr<mirror::String> name_string = mirror::String::AllocFromModifiedUtf8(self, name);
170*795d594fSAndroid Build Coastguard Worker       CHECK(name_string != nullptr);
171*795d594fSAndroid Build Coastguard Worker       CHECK(!self->IsExceptionPending());
172*795d594fSAndroid Build Coastguard Worker 
173*795d594fSAndroid Build Coastguard Worker       runner(self, shadow_frame.get(), name_string, &result);
174*795d594fSAndroid Build Coastguard Worker 
175*795d594fSAndroid Build Coastguard Worker       if (should_succeed) {
176*795d594fSAndroid Build Coastguard Worker         CHECK(!self->IsExceptionPending()) << name << " " << self->GetException()->Dump();
177*795d594fSAndroid Build Coastguard Worker         CHECK(result.GetL() != nullptr) << name;
178*795d594fSAndroid Build Coastguard Worker       } else {
179*795d594fSAndroid Build Coastguard Worker         CHECK(self->IsExceptionPending()) << name;
180*795d594fSAndroid Build Coastguard Worker         ASSERT_TRUE(IsTransactionAborted());
181*795d594fSAndroid Build Coastguard Worker         self->ClearException();
182*795d594fSAndroid Build Coastguard Worker       }
183*795d594fSAndroid Build Coastguard Worker 
184*795d594fSAndroid Build Coastguard Worker       ExitTransactionMode();
185*795d594fSAndroid Build Coastguard Worker     }
186*795d594fSAndroid Build Coastguard Worker   }
187*795d594fSAndroid Build Coastguard Worker };
188*795d594fSAndroid Build Coastguard Worker 
TEST_F(UnstartedClassForNameTransactionTest,ClassForNameLongWithClassLoader)189*795d594fSAndroid Build Coastguard Worker TEST_F(UnstartedClassForNameTransactionTest, ClassForNameLongWithClassLoader) {
190*795d594fSAndroid Build Coastguard Worker   Thread* self = Thread::Current();
191*795d594fSAndroid Build Coastguard Worker   ScopedObjectAccess soa(self);
192*795d594fSAndroid Build Coastguard Worker 
193*795d594fSAndroid Build Coastguard Worker   StackHandleScope<1> hs(self);
194*795d594fSAndroid Build Coastguard Worker   Handle<mirror::ClassLoader> boot_cp = hs.NewHandle(GetBootClassLoader());
195*795d594fSAndroid Build Coastguard Worker 
196*795d594fSAndroid Build Coastguard Worker   auto runner = [&](Thread* th,
197*795d594fSAndroid Build Coastguard Worker                     ShadowFrame* shadow_frame,
198*795d594fSAndroid Build Coastguard Worker                     ObjPtr<mirror::String> name,
199*795d594fSAndroid Build Coastguard Worker                     JValue* result)
200*795d594fSAndroid Build Coastguard Worker       REQUIRES_SHARED(Locks::mutator_lock_) {
201*795d594fSAndroid Build Coastguard Worker     shadow_frame->SetVRegReference(0, name);
202*795d594fSAndroid Build Coastguard Worker     shadow_frame->SetVReg(1, 0);
203*795d594fSAndroid Build Coastguard Worker     shadow_frame->SetVRegReference(2, boot_cp.Get());
204*795d594fSAndroid Build Coastguard Worker     UnstartedClassForNameLong(th, shadow_frame, result, 0);
205*795d594fSAndroid Build Coastguard Worker   };
206*795d594fSAndroid Build Coastguard Worker   RunTest(runner, /*should_succeed=*/ true);
207*795d594fSAndroid Build Coastguard Worker }
208*795d594fSAndroid Build Coastguard Worker 
TEST_F(UnstartedClassForNameTransactionTest,ClassForNameLongWithClassLoaderFail)209*795d594fSAndroid Build Coastguard Worker TEST_F(UnstartedClassForNameTransactionTest, ClassForNameLongWithClassLoaderFail) {
210*795d594fSAndroid Build Coastguard Worker   Thread* self = Thread::Current();
211*795d594fSAndroid Build Coastguard Worker   ScopedObjectAccess soa(self);
212*795d594fSAndroid Build Coastguard Worker 
213*795d594fSAndroid Build Coastguard Worker   StackHandleScope<2> hs(self);
214*795d594fSAndroid Build Coastguard Worker   jobject path_jobj = class_linker_->CreatePathClassLoader(self, {});
215*795d594fSAndroid Build Coastguard Worker   ASSERT_TRUE(path_jobj != nullptr);
216*795d594fSAndroid Build Coastguard Worker   Handle<mirror::ClassLoader> path_cp = hs.NewHandle<mirror::ClassLoader>(
217*795d594fSAndroid Build Coastguard Worker       self->DecodeJObject(path_jobj)->AsClassLoader());
218*795d594fSAndroid Build Coastguard Worker 
219*795d594fSAndroid Build Coastguard Worker   auto runner = [&](Thread* th,
220*795d594fSAndroid Build Coastguard Worker                     ShadowFrame* shadow_frame,
221*795d594fSAndroid Build Coastguard Worker                     ObjPtr<mirror::String> name,
222*795d594fSAndroid Build Coastguard Worker                     JValue* result) REQUIRES_SHARED(Locks::mutator_lock_) {
223*795d594fSAndroid Build Coastguard Worker     shadow_frame->SetVRegReference(0, name);
224*795d594fSAndroid Build Coastguard Worker     shadow_frame->SetVReg(1, 0);
225*795d594fSAndroid Build Coastguard Worker     shadow_frame->SetVRegReference(2, path_cp.Get());
226*795d594fSAndroid Build Coastguard Worker     UnstartedClassForNameLong(th, shadow_frame, result, 0);
227*795d594fSAndroid Build Coastguard Worker   };
228*795d594fSAndroid Build Coastguard Worker   RunTest(runner, /*should_succeed=*/ false);
229*795d594fSAndroid Build Coastguard Worker }
230*795d594fSAndroid Build Coastguard Worker 
231*795d594fSAndroid Build Coastguard Worker }  // namespace interpreter
232*795d594fSAndroid Build Coastguard Worker }  // namespace art
233