1*795d594fSAndroid Build Coastguard Worker /*
2*795d594fSAndroid Build Coastguard Worker * Copyright (C) 2014 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 "transaction.h"
18*795d594fSAndroid Build Coastguard Worker
19*795d594fSAndroid Build Coastguard Worker #include "art_field-inl.h"
20*795d594fSAndroid Build Coastguard Worker #include "art_method-inl.h"
21*795d594fSAndroid Build Coastguard Worker #include "class_linker-inl.h"
22*795d594fSAndroid Build Coastguard Worker #include "common_transaction_test.h"
23*795d594fSAndroid Build Coastguard Worker #include "common_throws.h"
24*795d594fSAndroid Build Coastguard Worker #include "dex/dex_file.h"
25*795d594fSAndroid Build Coastguard Worker #include "mirror/array-alloc-inl.h"
26*795d594fSAndroid Build Coastguard Worker #include "mirror/class-alloc-inl.h"
27*795d594fSAndroid Build Coastguard Worker #include "scoped_thread_state_change-inl.h"
28*795d594fSAndroid Build Coastguard Worker
29*795d594fSAndroid Build Coastguard Worker namespace art HIDDEN {
30*795d594fSAndroid Build Coastguard Worker
31*795d594fSAndroid Build Coastguard Worker class TransactionTest : public CommonTransactionTest {
32*795d594fSAndroid Build Coastguard Worker protected:
TransactionTest()33*795d594fSAndroid Build Coastguard Worker TransactionTest() {
34*795d594fSAndroid Build Coastguard Worker this->use_boot_image_ = true; // We need the boot image for this test.
35*795d594fSAndroid Build Coastguard Worker }
36*795d594fSAndroid Build Coastguard Worker
37*795d594fSAndroid Build Coastguard Worker // Tests failing class initialization due to native call with transaction rollback.
testTransactionAbort(const char * tested_class_signature)38*795d594fSAndroid Build Coastguard Worker void testTransactionAbort(const char* tested_class_signature) {
39*795d594fSAndroid Build Coastguard Worker ScopedObjectAccess soa(Thread::Current());
40*795d594fSAndroid Build Coastguard Worker jobject jclass_loader = LoadDex("Transaction");
41*795d594fSAndroid Build Coastguard Worker StackHandleScope<2> hs(soa.Self());
42*795d594fSAndroid Build Coastguard Worker Handle<mirror::ClassLoader> class_loader(
43*795d594fSAndroid Build Coastguard Worker hs.NewHandle(soa.Decode<mirror::ClassLoader>(jclass_loader)));
44*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(class_loader != nullptr);
45*795d594fSAndroid Build Coastguard Worker
46*795d594fSAndroid Build Coastguard Worker // Load and initialize java.lang.ExceptionInInitializerError and the exception class used
47*795d594fSAndroid Build Coastguard Worker // to abort transaction so they can be thrown during class initialization if the transaction
48*795d594fSAndroid Build Coastguard Worker // aborts.
49*795d594fSAndroid Build Coastguard Worker MutableHandle<mirror::Class> h_klass(
50*795d594fSAndroid Build Coastguard Worker hs.NewHandle(class_linker_->FindSystemClass(soa.Self(),
51*795d594fSAndroid Build Coastguard Worker "Ljava/lang/ExceptionInInitializerError;")));
52*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(h_klass != nullptr);
53*795d594fSAndroid Build Coastguard Worker class_linker_->EnsureInitialized(soa.Self(), h_klass, true, true);
54*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(h_klass->IsInitialized());
55*795d594fSAndroid Build Coastguard Worker
56*795d594fSAndroid Build Coastguard Worker h_klass.Assign(class_linker_->FindSystemClass(soa.Self(), kTransactionAbortErrorDescriptor));
57*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(h_klass != nullptr);
58*795d594fSAndroid Build Coastguard Worker class_linker_->EnsureInitialized(soa.Self(), h_klass, true, true);
59*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(h_klass->IsInitialized());
60*795d594fSAndroid Build Coastguard Worker
61*795d594fSAndroid Build Coastguard Worker // Load and verify utility class.
62*795d594fSAndroid Build Coastguard Worker h_klass.Assign(FindClass("LTransaction$AbortHelperClass;", class_loader));
63*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(h_klass != nullptr);
64*795d594fSAndroid Build Coastguard Worker class_linker_->VerifyClass(soa.Self(), /* verifier_deps= */ nullptr, h_klass);
65*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(h_klass->IsVerified());
66*795d594fSAndroid Build Coastguard Worker
67*795d594fSAndroid Build Coastguard Worker // Load and verify tested class.
68*795d594fSAndroid Build Coastguard Worker h_klass.Assign(FindClass(tested_class_signature, class_loader));
69*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(h_klass != nullptr);
70*795d594fSAndroid Build Coastguard Worker class_linker_->VerifyClass(soa.Self(), /* verifier_deps= */ nullptr, h_klass);
71*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(h_klass->IsVerified());
72*795d594fSAndroid Build Coastguard Worker
73*795d594fSAndroid Build Coastguard Worker ClassStatus old_status = h_klass->GetStatus();
74*795d594fSAndroid Build Coastguard Worker LockWord old_lock_word = h_klass->GetLockWord(false);
75*795d594fSAndroid Build Coastguard Worker
76*795d594fSAndroid Build Coastguard Worker EnterTransactionMode();
77*795d594fSAndroid Build Coastguard Worker bool success = class_linker_->EnsureInitialized(soa.Self(), h_klass, true, true);
78*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(IsTransactionAborted());
79*795d594fSAndroid Build Coastguard Worker ASSERT_FALSE(success);
80*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(h_klass->IsErroneous());
81*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(soa.Self()->IsExceptionPending());
82*795d594fSAndroid Build Coastguard Worker
83*795d594fSAndroid Build Coastguard Worker // Check class's monitor get back to its original state without rolling back changes.
84*795d594fSAndroid Build Coastguard Worker LockWord new_lock_word = h_klass->GetLockWord(false);
85*795d594fSAndroid Build Coastguard Worker EXPECT_TRUE(LockWord::Equal<false>(old_lock_word, new_lock_word));
86*795d594fSAndroid Build Coastguard Worker
87*795d594fSAndroid Build Coastguard Worker // Check class status is rolled back properly.
88*795d594fSAndroid Build Coastguard Worker soa.Self()->ClearException();
89*795d594fSAndroid Build Coastguard Worker RollbackAndExitTransactionMode();
90*795d594fSAndroid Build Coastguard Worker ASSERT_EQ(old_status, h_klass->GetStatus());
91*795d594fSAndroid Build Coastguard Worker }
92*795d594fSAndroid Build Coastguard Worker };
93*795d594fSAndroid Build Coastguard Worker
94*795d594fSAndroid Build Coastguard Worker // Tests object's class is preserved after transaction rollback.
TEST_F(TransactionTest,Object_class)95*795d594fSAndroid Build Coastguard Worker TEST_F(TransactionTest, Object_class) {
96*795d594fSAndroid Build Coastguard Worker ScopedObjectAccess soa(Thread::Current());
97*795d594fSAndroid Build Coastguard Worker StackHandleScope<2> hs(soa.Self());
98*795d594fSAndroid Build Coastguard Worker Handle<mirror::Class> h_klass(
99*795d594fSAndroid Build Coastguard Worker hs.NewHandle(class_linker_->FindSystemClass(soa.Self(), "Ljava/lang/Object;")));
100*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(h_klass != nullptr);
101*795d594fSAndroid Build Coastguard Worker
102*795d594fSAndroid Build Coastguard Worker EnterTransactionMode();
103*795d594fSAndroid Build Coastguard Worker Handle<mirror::Object> h_obj(hs.NewHandle(h_klass->AllocObject(soa.Self())));
104*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(h_obj != nullptr);
105*795d594fSAndroid Build Coastguard Worker ASSERT_OBJ_PTR_EQ(h_obj->GetClass(), h_klass.Get());
106*795d594fSAndroid Build Coastguard Worker // Rolling back transaction's changes must not clear the Object::class field.
107*795d594fSAndroid Build Coastguard Worker RollbackAndExitTransactionMode();
108*795d594fSAndroid Build Coastguard Worker EXPECT_OBJ_PTR_EQ(h_obj->GetClass(), h_klass.Get());
109*795d594fSAndroid Build Coastguard Worker }
110*795d594fSAndroid Build Coastguard Worker
111*795d594fSAndroid Build Coastguard Worker // Tests object's monitor state is preserved after transaction rollback.
TEST_F(TransactionTest,Object_monitor)112*795d594fSAndroid Build Coastguard Worker TEST_F(TransactionTest, Object_monitor) {
113*795d594fSAndroid Build Coastguard Worker ScopedObjectAccess soa(Thread::Current());
114*795d594fSAndroid Build Coastguard Worker StackHandleScope<2> hs(soa.Self());
115*795d594fSAndroid Build Coastguard Worker Handle<mirror::Class> h_klass(
116*795d594fSAndroid Build Coastguard Worker hs.NewHandle(class_linker_->FindSystemClass(soa.Self(), "Ljava/lang/Object;")));
117*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(h_klass != nullptr);
118*795d594fSAndroid Build Coastguard Worker Handle<mirror::Object> h_obj(hs.NewHandle(h_klass->AllocObject(soa.Self())));
119*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(h_obj != nullptr);
120*795d594fSAndroid Build Coastguard Worker ASSERT_OBJ_PTR_EQ(h_obj->GetClass(), h_klass.Get());
121*795d594fSAndroid Build Coastguard Worker
122*795d594fSAndroid Build Coastguard Worker // Lock object's monitor outside the transaction.
123*795d594fSAndroid Build Coastguard Worker h_obj->MonitorEnter(soa.Self());
124*795d594fSAndroid Build Coastguard Worker LockWord old_lock_word = h_obj->GetLockWord(false);
125*795d594fSAndroid Build Coastguard Worker
126*795d594fSAndroid Build Coastguard Worker EnterTransactionMode();
127*795d594fSAndroid Build Coastguard Worker // Unlock object's monitor inside the transaction.
128*795d594fSAndroid Build Coastguard Worker h_obj->MonitorExit(soa.Self());
129*795d594fSAndroid Build Coastguard Worker LockWord new_lock_word = h_obj->GetLockWord(false);
130*795d594fSAndroid Build Coastguard Worker // Rolling back transaction's changes must not change monitor's state.
131*795d594fSAndroid Build Coastguard Worker RollbackAndExitTransactionMode();
132*795d594fSAndroid Build Coastguard Worker
133*795d594fSAndroid Build Coastguard Worker LockWord aborted_lock_word = h_obj->GetLockWord(false);
134*795d594fSAndroid Build Coastguard Worker EXPECT_FALSE(LockWord::Equal<false>(old_lock_word, new_lock_word));
135*795d594fSAndroid Build Coastguard Worker EXPECT_TRUE(LockWord::Equal<false>(aborted_lock_word, new_lock_word));
136*795d594fSAndroid Build Coastguard Worker }
137*795d594fSAndroid Build Coastguard Worker
138*795d594fSAndroid Build Coastguard Worker // Tests array's length is preserved after transaction rollback.
TEST_F(TransactionTest,Array_length)139*795d594fSAndroid Build Coastguard Worker TEST_F(TransactionTest, Array_length) {
140*795d594fSAndroid Build Coastguard Worker ScopedObjectAccess soa(Thread::Current());
141*795d594fSAndroid Build Coastguard Worker StackHandleScope<2> hs(soa.Self());
142*795d594fSAndroid Build Coastguard Worker Handle<mirror::Class> h_klass(
143*795d594fSAndroid Build Coastguard Worker hs.NewHandle(class_linker_->FindSystemClass(soa.Self(), "[Ljava/lang/Object;")));
144*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(h_klass != nullptr);
145*795d594fSAndroid Build Coastguard Worker
146*795d594fSAndroid Build Coastguard Worker constexpr int32_t kArraySize = 2;
147*795d594fSAndroid Build Coastguard Worker
148*795d594fSAndroid Build Coastguard Worker EnterTransactionMode();
149*795d594fSAndroid Build Coastguard Worker
150*795d594fSAndroid Build Coastguard Worker // Allocate an array during transaction.
151*795d594fSAndroid Build Coastguard Worker Handle<mirror::Array> h_obj = hs.NewHandle(
152*795d594fSAndroid Build Coastguard Worker mirror::Array::Alloc(soa.Self(),
153*795d594fSAndroid Build Coastguard Worker h_klass.Get(),
154*795d594fSAndroid Build Coastguard Worker kArraySize,
155*795d594fSAndroid Build Coastguard Worker h_klass->GetComponentSizeShift(),
156*795d594fSAndroid Build Coastguard Worker Runtime::Current()->GetHeap()->GetCurrentAllocator()));
157*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(h_obj != nullptr);
158*795d594fSAndroid Build Coastguard Worker ASSERT_OBJ_PTR_EQ(h_obj->GetClass(), h_klass.Get());
159*795d594fSAndroid Build Coastguard Worker RollbackAndExitTransactionMode();
160*795d594fSAndroid Build Coastguard Worker
161*795d594fSAndroid Build Coastguard Worker // Rolling back transaction's changes must not reset array's length.
162*795d594fSAndroid Build Coastguard Worker EXPECT_EQ(h_obj->GetLength(), kArraySize);
163*795d594fSAndroid Build Coastguard Worker }
164*795d594fSAndroid Build Coastguard Worker
165*795d594fSAndroid Build Coastguard Worker // Tests static fields are reset to their default value after transaction rollback.
TEST_F(TransactionTest,StaticFieldsTest)166*795d594fSAndroid Build Coastguard Worker TEST_F(TransactionTest, StaticFieldsTest) {
167*795d594fSAndroid Build Coastguard Worker ScopedObjectAccess soa(Thread::Current());
168*795d594fSAndroid Build Coastguard Worker StackHandleScope<4> hs(soa.Self());
169*795d594fSAndroid Build Coastguard Worker Handle<mirror::ClassLoader> class_loader(
170*795d594fSAndroid Build Coastguard Worker hs.NewHandle(soa.Decode<mirror::ClassLoader>(LoadDex("Transaction"))));
171*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(class_loader != nullptr);
172*795d594fSAndroid Build Coastguard Worker
173*795d594fSAndroid Build Coastguard Worker Handle<mirror::Class> h_klass = hs.NewHandle(FindClass("LStaticFieldsTest;", class_loader));
174*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(h_klass != nullptr);
175*795d594fSAndroid Build Coastguard Worker bool success = class_linker_->EnsureInitialized(soa.Self(), h_klass, true, true);
176*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(success);
177*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(h_klass->IsInitialized());
178*795d594fSAndroid Build Coastguard Worker ASSERT_FALSE(soa.Self()->IsExceptionPending());
179*795d594fSAndroid Build Coastguard Worker
180*795d594fSAndroid Build Coastguard Worker // Lookup fields.
181*795d594fSAndroid Build Coastguard Worker ArtField* booleanField = h_klass->FindDeclaredStaticField("booleanField", "Z");
182*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(booleanField != nullptr);
183*795d594fSAndroid Build Coastguard Worker ASSERT_EQ(booleanField->GetTypeAsPrimitiveType(), Primitive::kPrimBoolean);
184*795d594fSAndroid Build Coastguard Worker ASSERT_EQ(booleanField->GetBoolean(h_klass.Get()), false);
185*795d594fSAndroid Build Coastguard Worker
186*795d594fSAndroid Build Coastguard Worker ArtField* byteField = h_klass->FindDeclaredStaticField("byteField", "B");
187*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(byteField != nullptr);
188*795d594fSAndroid Build Coastguard Worker ASSERT_EQ(byteField->GetTypeAsPrimitiveType(), Primitive::kPrimByte);
189*795d594fSAndroid Build Coastguard Worker ASSERT_EQ(byteField->GetByte(h_klass.Get()), 0);
190*795d594fSAndroid Build Coastguard Worker
191*795d594fSAndroid Build Coastguard Worker ArtField* charField = h_klass->FindDeclaredStaticField("charField", "C");
192*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(charField != nullptr);
193*795d594fSAndroid Build Coastguard Worker ASSERT_EQ(charField->GetTypeAsPrimitiveType(), Primitive::kPrimChar);
194*795d594fSAndroid Build Coastguard Worker ASSERT_EQ(charField->GetChar(h_klass.Get()), 0u);
195*795d594fSAndroid Build Coastguard Worker
196*795d594fSAndroid Build Coastguard Worker ArtField* shortField = h_klass->FindDeclaredStaticField("shortField", "S");
197*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(shortField != nullptr);
198*795d594fSAndroid Build Coastguard Worker ASSERT_EQ(shortField->GetTypeAsPrimitiveType(), Primitive::kPrimShort);
199*795d594fSAndroid Build Coastguard Worker ASSERT_EQ(shortField->GetShort(h_klass.Get()), 0);
200*795d594fSAndroid Build Coastguard Worker
201*795d594fSAndroid Build Coastguard Worker ArtField* intField = h_klass->FindDeclaredStaticField("intField", "I");
202*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(intField != nullptr);
203*795d594fSAndroid Build Coastguard Worker ASSERT_EQ(intField->GetTypeAsPrimitiveType(), Primitive::kPrimInt);
204*795d594fSAndroid Build Coastguard Worker ASSERT_EQ(intField->GetInt(h_klass.Get()), 0);
205*795d594fSAndroid Build Coastguard Worker
206*795d594fSAndroid Build Coastguard Worker ArtField* longField = h_klass->FindDeclaredStaticField("longField", "J");
207*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(longField != nullptr);
208*795d594fSAndroid Build Coastguard Worker ASSERT_EQ(longField->GetTypeAsPrimitiveType(), Primitive::kPrimLong);
209*795d594fSAndroid Build Coastguard Worker ASSERT_EQ(longField->GetLong(h_klass.Get()), static_cast<int64_t>(0));
210*795d594fSAndroid Build Coastguard Worker
211*795d594fSAndroid Build Coastguard Worker ArtField* floatField = h_klass->FindDeclaredStaticField("floatField", "F");
212*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(floatField != nullptr);
213*795d594fSAndroid Build Coastguard Worker ASSERT_EQ(floatField->GetTypeAsPrimitiveType(), Primitive::kPrimFloat);
214*795d594fSAndroid Build Coastguard Worker ASSERT_FLOAT_EQ(floatField->GetFloat(h_klass.Get()), static_cast<float>(0.0f));
215*795d594fSAndroid Build Coastguard Worker
216*795d594fSAndroid Build Coastguard Worker ArtField* doubleField = h_klass->FindDeclaredStaticField("doubleField", "D");
217*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(doubleField != nullptr);
218*795d594fSAndroid Build Coastguard Worker ASSERT_EQ(doubleField->GetTypeAsPrimitiveType(), Primitive::kPrimDouble);
219*795d594fSAndroid Build Coastguard Worker ASSERT_DOUBLE_EQ(doubleField->GetDouble(h_klass.Get()), static_cast<double>(0.0));
220*795d594fSAndroid Build Coastguard Worker
221*795d594fSAndroid Build Coastguard Worker ArtField* objectField = h_klass->FindDeclaredStaticField("objectField",
222*795d594fSAndroid Build Coastguard Worker "Ljava/lang/Object;");
223*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(objectField != nullptr);
224*795d594fSAndroid Build Coastguard Worker ASSERT_EQ(objectField->GetTypeAsPrimitiveType(), Primitive::kPrimNot);
225*795d594fSAndroid Build Coastguard Worker ASSERT_EQ(objectField->GetObject(h_klass.Get()), nullptr);
226*795d594fSAndroid Build Coastguard Worker
227*795d594fSAndroid Build Coastguard Worker // Create a java.lang.Object instance to set objectField.
228*795d594fSAndroid Build Coastguard Worker Handle<mirror::Class> object_klass(
229*795d594fSAndroid Build Coastguard Worker hs.NewHandle(class_linker_->FindSystemClass(soa.Self(), "Ljava/lang/Object;")));
230*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(object_klass != nullptr);
231*795d594fSAndroid Build Coastguard Worker Handle<mirror::Object> h_obj(hs.NewHandle(h_klass->AllocObject(soa.Self())));
232*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(h_obj != nullptr);
233*795d594fSAndroid Build Coastguard Worker ASSERT_OBJ_PTR_EQ(h_obj->GetClass(), h_klass.Get());
234*795d594fSAndroid Build Coastguard Worker
235*795d594fSAndroid Build Coastguard Worker // Modify fields inside transaction then rollback changes.
236*795d594fSAndroid Build Coastguard Worker EnterTransactionMode();
237*795d594fSAndroid Build Coastguard Worker booleanField->SetBoolean<true>(h_klass.Get(), true);
238*795d594fSAndroid Build Coastguard Worker byteField->SetByte<true>(h_klass.Get(), 1);
239*795d594fSAndroid Build Coastguard Worker charField->SetChar<true>(h_klass.Get(), 1u);
240*795d594fSAndroid Build Coastguard Worker shortField->SetShort<true>(h_klass.Get(), 1);
241*795d594fSAndroid Build Coastguard Worker intField->SetInt<true>(h_klass.Get(), 1);
242*795d594fSAndroid Build Coastguard Worker longField->SetLong<true>(h_klass.Get(), 1);
243*795d594fSAndroid Build Coastguard Worker floatField->SetFloat<true>(h_klass.Get(), 1.0);
244*795d594fSAndroid Build Coastguard Worker doubleField->SetDouble<true>(h_klass.Get(), 1.0);
245*795d594fSAndroid Build Coastguard Worker objectField->SetObject<true>(h_klass.Get(), h_obj.Get());
246*795d594fSAndroid Build Coastguard Worker RollbackAndExitTransactionMode();
247*795d594fSAndroid Build Coastguard Worker
248*795d594fSAndroid Build Coastguard Worker // Check values have properly been restored to their original (default) value.
249*795d594fSAndroid Build Coastguard Worker EXPECT_EQ(booleanField->GetBoolean(h_klass.Get()), false);
250*795d594fSAndroid Build Coastguard Worker EXPECT_EQ(byteField->GetByte(h_klass.Get()), 0);
251*795d594fSAndroid Build Coastguard Worker EXPECT_EQ(charField->GetChar(h_klass.Get()), 0u);
252*795d594fSAndroid Build Coastguard Worker EXPECT_EQ(shortField->GetShort(h_klass.Get()), 0);
253*795d594fSAndroid Build Coastguard Worker EXPECT_EQ(intField->GetInt(h_klass.Get()), 0);
254*795d594fSAndroid Build Coastguard Worker EXPECT_EQ(longField->GetLong(h_klass.Get()), static_cast<int64_t>(0));
255*795d594fSAndroid Build Coastguard Worker EXPECT_FLOAT_EQ(floatField->GetFloat(h_klass.Get()), static_cast<float>(0.0f));
256*795d594fSAndroid Build Coastguard Worker EXPECT_DOUBLE_EQ(doubleField->GetDouble(h_klass.Get()), static_cast<double>(0.0));
257*795d594fSAndroid Build Coastguard Worker EXPECT_EQ(objectField->GetObject(h_klass.Get()), nullptr);
258*795d594fSAndroid Build Coastguard Worker }
259*795d594fSAndroid Build Coastguard Worker
260*795d594fSAndroid Build Coastguard Worker // Tests instance fields are reset to their default value after transaction rollback.
TEST_F(TransactionTest,InstanceFieldsTest)261*795d594fSAndroid Build Coastguard Worker TEST_F(TransactionTest, InstanceFieldsTest) {
262*795d594fSAndroid Build Coastguard Worker ScopedObjectAccess soa(Thread::Current());
263*795d594fSAndroid Build Coastguard Worker StackHandleScope<5> hs(soa.Self());
264*795d594fSAndroid Build Coastguard Worker Handle<mirror::ClassLoader> class_loader(
265*795d594fSAndroid Build Coastguard Worker hs.NewHandle(soa.Decode<mirror::ClassLoader>(LoadDex("Transaction"))));
266*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(class_loader != nullptr);
267*795d594fSAndroid Build Coastguard Worker
268*795d594fSAndroid Build Coastguard Worker Handle<mirror::Class> h_klass = hs.NewHandle(FindClass("LInstanceFieldsTest;", class_loader));
269*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(h_klass != nullptr);
270*795d594fSAndroid Build Coastguard Worker bool success = class_linker_->EnsureInitialized(soa.Self(), h_klass, true, true);
271*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(success);
272*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(h_klass->IsInitialized());
273*795d594fSAndroid Build Coastguard Worker ASSERT_FALSE(soa.Self()->IsExceptionPending());
274*795d594fSAndroid Build Coastguard Worker
275*795d594fSAndroid Build Coastguard Worker // Allocate an InstanceFieldTest object.
276*795d594fSAndroid Build Coastguard Worker Handle<mirror::Object> h_instance(hs.NewHandle(h_klass->AllocObject(soa.Self())));
277*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(h_instance != nullptr);
278*795d594fSAndroid Build Coastguard Worker
279*795d594fSAndroid Build Coastguard Worker // Lookup fields.
280*795d594fSAndroid Build Coastguard Worker ArtField* booleanField = h_klass->FindDeclaredInstanceField("booleanField", "Z");
281*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(booleanField != nullptr);
282*795d594fSAndroid Build Coastguard Worker ASSERT_EQ(booleanField->GetTypeAsPrimitiveType(), Primitive::kPrimBoolean);
283*795d594fSAndroid Build Coastguard Worker ASSERT_EQ(booleanField->GetBoolean(h_instance.Get()), false);
284*795d594fSAndroid Build Coastguard Worker
285*795d594fSAndroid Build Coastguard Worker ArtField* byteField = h_klass->FindDeclaredInstanceField("byteField", "B");
286*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(byteField != nullptr);
287*795d594fSAndroid Build Coastguard Worker ASSERT_EQ(byteField->GetTypeAsPrimitiveType(), Primitive::kPrimByte);
288*795d594fSAndroid Build Coastguard Worker ASSERT_EQ(byteField->GetByte(h_instance.Get()), 0);
289*795d594fSAndroid Build Coastguard Worker
290*795d594fSAndroid Build Coastguard Worker ArtField* charField = h_klass->FindDeclaredInstanceField("charField", "C");
291*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(charField != nullptr);
292*795d594fSAndroid Build Coastguard Worker ASSERT_EQ(charField->GetTypeAsPrimitiveType(), Primitive::kPrimChar);
293*795d594fSAndroid Build Coastguard Worker ASSERT_EQ(charField->GetChar(h_instance.Get()), 0u);
294*795d594fSAndroid Build Coastguard Worker
295*795d594fSAndroid Build Coastguard Worker ArtField* shortField = h_klass->FindDeclaredInstanceField("shortField", "S");
296*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(shortField != nullptr);
297*795d594fSAndroid Build Coastguard Worker ASSERT_EQ(shortField->GetTypeAsPrimitiveType(), Primitive::kPrimShort);
298*795d594fSAndroid Build Coastguard Worker ASSERT_EQ(shortField->GetShort(h_instance.Get()), 0);
299*795d594fSAndroid Build Coastguard Worker
300*795d594fSAndroid Build Coastguard Worker ArtField* intField = h_klass->FindDeclaredInstanceField("intField", "I");
301*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(intField != nullptr);
302*795d594fSAndroid Build Coastguard Worker ASSERT_EQ(intField->GetTypeAsPrimitiveType(), Primitive::kPrimInt);
303*795d594fSAndroid Build Coastguard Worker ASSERT_EQ(intField->GetInt(h_instance.Get()), 0);
304*795d594fSAndroid Build Coastguard Worker
305*795d594fSAndroid Build Coastguard Worker ArtField* longField = h_klass->FindDeclaredInstanceField("longField", "J");
306*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(longField != nullptr);
307*795d594fSAndroid Build Coastguard Worker ASSERT_EQ(longField->GetTypeAsPrimitiveType(), Primitive::kPrimLong);
308*795d594fSAndroid Build Coastguard Worker ASSERT_EQ(longField->GetLong(h_instance.Get()), static_cast<int64_t>(0));
309*795d594fSAndroid Build Coastguard Worker
310*795d594fSAndroid Build Coastguard Worker ArtField* floatField = h_klass->FindDeclaredInstanceField("floatField", "F");
311*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(floatField != nullptr);
312*795d594fSAndroid Build Coastguard Worker ASSERT_EQ(floatField->GetTypeAsPrimitiveType(), Primitive::kPrimFloat);
313*795d594fSAndroid Build Coastguard Worker ASSERT_FLOAT_EQ(floatField->GetFloat(h_instance.Get()), static_cast<float>(0.0f));
314*795d594fSAndroid Build Coastguard Worker
315*795d594fSAndroid Build Coastguard Worker ArtField* doubleField = h_klass->FindDeclaredInstanceField("doubleField", "D");
316*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(doubleField != nullptr);
317*795d594fSAndroid Build Coastguard Worker ASSERT_EQ(doubleField->GetTypeAsPrimitiveType(), Primitive::kPrimDouble);
318*795d594fSAndroid Build Coastguard Worker ASSERT_DOUBLE_EQ(doubleField->GetDouble(h_instance.Get()), static_cast<double>(0.0));
319*795d594fSAndroid Build Coastguard Worker
320*795d594fSAndroid Build Coastguard Worker ArtField* objectField = h_klass->FindDeclaredInstanceField("objectField",
321*795d594fSAndroid Build Coastguard Worker "Ljava/lang/Object;");
322*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(objectField != nullptr);
323*795d594fSAndroid Build Coastguard Worker ASSERT_EQ(objectField->GetTypeAsPrimitiveType(), Primitive::kPrimNot);
324*795d594fSAndroid Build Coastguard Worker ASSERT_EQ(objectField->GetObject(h_instance.Get()), nullptr);
325*795d594fSAndroid Build Coastguard Worker
326*795d594fSAndroid Build Coastguard Worker // Create a java.lang.Object instance to set objectField.
327*795d594fSAndroid Build Coastguard Worker Handle<mirror::Class> object_klass(
328*795d594fSAndroid Build Coastguard Worker hs.NewHandle(class_linker_->FindSystemClass(soa.Self(), "Ljava/lang/Object;")));
329*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(object_klass != nullptr);
330*795d594fSAndroid Build Coastguard Worker Handle<mirror::Object> h_obj(hs.NewHandle(h_klass->AllocObject(soa.Self())));
331*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(h_obj != nullptr);
332*795d594fSAndroid Build Coastguard Worker ASSERT_OBJ_PTR_EQ(h_obj->GetClass(), h_klass.Get());
333*795d594fSAndroid Build Coastguard Worker
334*795d594fSAndroid Build Coastguard Worker // Modify fields inside transaction then rollback changes.
335*795d594fSAndroid Build Coastguard Worker EnterTransactionMode();
336*795d594fSAndroid Build Coastguard Worker booleanField->SetBoolean<true>(h_instance.Get(), true);
337*795d594fSAndroid Build Coastguard Worker byteField->SetByte<true>(h_instance.Get(), 1);
338*795d594fSAndroid Build Coastguard Worker charField->SetChar<true>(h_instance.Get(), 1u);
339*795d594fSAndroid Build Coastguard Worker shortField->SetShort<true>(h_instance.Get(), 1);
340*795d594fSAndroid Build Coastguard Worker intField->SetInt<true>(h_instance.Get(), 1);
341*795d594fSAndroid Build Coastguard Worker longField->SetLong<true>(h_instance.Get(), 1);
342*795d594fSAndroid Build Coastguard Worker floatField->SetFloat<true>(h_instance.Get(), 1.0);
343*795d594fSAndroid Build Coastguard Worker doubleField->SetDouble<true>(h_instance.Get(), 1.0);
344*795d594fSAndroid Build Coastguard Worker objectField->SetObject<true>(h_instance.Get(), h_obj.Get());
345*795d594fSAndroid Build Coastguard Worker RollbackAndExitTransactionMode();
346*795d594fSAndroid Build Coastguard Worker
347*795d594fSAndroid Build Coastguard Worker // Check values have properly been restored to their original (default) value.
348*795d594fSAndroid Build Coastguard Worker EXPECT_EQ(booleanField->GetBoolean(h_instance.Get()), false);
349*795d594fSAndroid Build Coastguard Worker EXPECT_EQ(byteField->GetByte(h_instance.Get()), 0);
350*795d594fSAndroid Build Coastguard Worker EXPECT_EQ(charField->GetChar(h_instance.Get()), 0u);
351*795d594fSAndroid Build Coastguard Worker EXPECT_EQ(shortField->GetShort(h_instance.Get()), 0);
352*795d594fSAndroid Build Coastguard Worker EXPECT_EQ(intField->GetInt(h_instance.Get()), 0);
353*795d594fSAndroid Build Coastguard Worker EXPECT_EQ(longField->GetLong(h_instance.Get()), static_cast<int64_t>(0));
354*795d594fSAndroid Build Coastguard Worker EXPECT_FLOAT_EQ(floatField->GetFloat(h_instance.Get()), static_cast<float>(0.0f));
355*795d594fSAndroid Build Coastguard Worker EXPECT_DOUBLE_EQ(doubleField->GetDouble(h_instance.Get()), static_cast<double>(0.0));
356*795d594fSAndroid Build Coastguard Worker EXPECT_EQ(objectField->GetObject(h_instance.Get()), nullptr);
357*795d594fSAndroid Build Coastguard Worker
358*795d594fSAndroid Build Coastguard Worker // Fail to modify fields with strong CAS inside transaction, then rollback changes.
359*795d594fSAndroid Build Coastguard Worker EnterTransactionMode();
360*795d594fSAndroid Build Coastguard Worker bool cas_success = h_instance->CasField32</*kTransactionActive=*/ true>(
361*795d594fSAndroid Build Coastguard Worker intField->GetOffset(),
362*795d594fSAndroid Build Coastguard Worker /*old_value=*/ 1,
363*795d594fSAndroid Build Coastguard Worker /*new_value=*/ 2,
364*795d594fSAndroid Build Coastguard Worker CASMode::kStrong,
365*795d594fSAndroid Build Coastguard Worker std::memory_order_seq_cst);
366*795d594fSAndroid Build Coastguard Worker EXPECT_FALSE(cas_success);
367*795d594fSAndroid Build Coastguard Worker cas_success = h_instance->CasFieldStrongSequentiallyConsistent64</*kTransactionActive=*/ true>(
368*795d594fSAndroid Build Coastguard Worker longField->GetOffset(), /*old_value=*/ INT64_C(1), /*new_value=*/ INT64_C(2));
369*795d594fSAndroid Build Coastguard Worker EXPECT_FALSE(cas_success);
370*795d594fSAndroid Build Coastguard Worker cas_success = h_instance->CasFieldObject</*kTransactionActive=*/ true>(
371*795d594fSAndroid Build Coastguard Worker objectField->GetOffset(),
372*795d594fSAndroid Build Coastguard Worker /*old_value=*/ h_instance.Get(),
373*795d594fSAndroid Build Coastguard Worker /*new_value=*/ nullptr,
374*795d594fSAndroid Build Coastguard Worker CASMode::kStrong,
375*795d594fSAndroid Build Coastguard Worker std::memory_order_seq_cst);
376*795d594fSAndroid Build Coastguard Worker EXPECT_FALSE(cas_success);
377*795d594fSAndroid Build Coastguard Worker RollbackAndExitTransactionMode();
378*795d594fSAndroid Build Coastguard Worker
379*795d594fSAndroid Build Coastguard Worker // Check values have properly been restored to their original (default) value.
380*795d594fSAndroid Build Coastguard Worker EXPECT_EQ(intField->GetInt(h_instance.Get()), 0);
381*795d594fSAndroid Build Coastguard Worker EXPECT_EQ(longField->GetLong(h_instance.Get()), static_cast<int64_t>(0));
382*795d594fSAndroid Build Coastguard Worker EXPECT_EQ(objectField->GetObject(h_instance.Get()), nullptr);
383*795d594fSAndroid Build Coastguard Worker
384*795d594fSAndroid Build Coastguard Worker // Fail to modify fields with weak CAS inside transaction, then rollback changes.
385*795d594fSAndroid Build Coastguard Worker EnterTransactionMode();
386*795d594fSAndroid Build Coastguard Worker cas_success = h_instance->CasField32</*kTransactionActive=*/ true>(
387*795d594fSAndroid Build Coastguard Worker intField->GetOffset(),
388*795d594fSAndroid Build Coastguard Worker /*old_value=*/ 3,
389*795d594fSAndroid Build Coastguard Worker /*new_value=*/ 4,
390*795d594fSAndroid Build Coastguard Worker CASMode::kWeak,
391*795d594fSAndroid Build Coastguard Worker std::memory_order_seq_cst);
392*795d594fSAndroid Build Coastguard Worker EXPECT_FALSE(cas_success);
393*795d594fSAndroid Build Coastguard Worker cas_success = h_instance->CasFieldWeakSequentiallyConsistent64</*kTransactionActive=*/ true>(
394*795d594fSAndroid Build Coastguard Worker longField->GetOffset(), /*old_value=*/ INT64_C(3), /*new_value=*/ INT64_C(4));
395*795d594fSAndroid Build Coastguard Worker EXPECT_FALSE(cas_success);
396*795d594fSAndroid Build Coastguard Worker cas_success = h_instance->CasFieldObject</*kTransactionActive=*/ true>(
397*795d594fSAndroid Build Coastguard Worker objectField->GetOffset(),
398*795d594fSAndroid Build Coastguard Worker /*old_value=*/ h_klass.Get(),
399*795d594fSAndroid Build Coastguard Worker /*new_value=*/ nullptr,
400*795d594fSAndroid Build Coastguard Worker CASMode::kWeak,
401*795d594fSAndroid Build Coastguard Worker std::memory_order_seq_cst);
402*795d594fSAndroid Build Coastguard Worker EXPECT_FALSE(cas_success);
403*795d594fSAndroid Build Coastguard Worker RollbackAndExitTransactionMode();
404*795d594fSAndroid Build Coastguard Worker
405*795d594fSAndroid Build Coastguard Worker // Check values have properly been restored to their original (default) value.
406*795d594fSAndroid Build Coastguard Worker EXPECT_EQ(intField->GetInt(h_instance.Get()), 0);
407*795d594fSAndroid Build Coastguard Worker EXPECT_EQ(longField->GetLong(h_instance.Get()), static_cast<int64_t>(0));
408*795d594fSAndroid Build Coastguard Worker EXPECT_EQ(objectField->GetObject(h_instance.Get()), nullptr);
409*795d594fSAndroid Build Coastguard Worker }
410*795d594fSAndroid Build Coastguard Worker
411*795d594fSAndroid Build Coastguard Worker // Tests static array fields are reset to their default value after transaction rollback.
TEST_F(TransactionTest,StaticArrayFieldsTest)412*795d594fSAndroid Build Coastguard Worker TEST_F(TransactionTest, StaticArrayFieldsTest) {
413*795d594fSAndroid Build Coastguard Worker ScopedObjectAccess soa(Thread::Current());
414*795d594fSAndroid Build Coastguard Worker StackHandleScope<13> hs(soa.Self());
415*795d594fSAndroid Build Coastguard Worker Handle<mirror::ClassLoader> class_loader(
416*795d594fSAndroid Build Coastguard Worker hs.NewHandle(soa.Decode<mirror::ClassLoader>(LoadDex("Transaction"))));
417*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(class_loader != nullptr);
418*795d594fSAndroid Build Coastguard Worker
419*795d594fSAndroid Build Coastguard Worker Handle<mirror::Class> h_klass = hs.NewHandle(FindClass("LStaticArrayFieldsTest;", class_loader));
420*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(h_klass != nullptr);
421*795d594fSAndroid Build Coastguard Worker bool success = class_linker_->EnsureInitialized(soa.Self(), h_klass, true, true);
422*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(success);
423*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(h_klass->IsInitialized());
424*795d594fSAndroid Build Coastguard Worker ASSERT_FALSE(soa.Self()->IsExceptionPending());
425*795d594fSAndroid Build Coastguard Worker
426*795d594fSAndroid Build Coastguard Worker // Lookup fields.
427*795d594fSAndroid Build Coastguard Worker ArtField* booleanArrayField = h_klass->FindDeclaredStaticField("booleanArrayField", "[Z");
428*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(booleanArrayField != nullptr);
429*795d594fSAndroid Build Coastguard Worker Handle<mirror::BooleanArray> booleanArray = hs.NewHandle(
430*795d594fSAndroid Build Coastguard Worker booleanArrayField->GetObject(h_klass.Get())->AsBooleanArray());
431*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(booleanArray != nullptr);
432*795d594fSAndroid Build Coastguard Worker ASSERT_EQ(booleanArray->GetLength(), 1);
433*795d594fSAndroid Build Coastguard Worker ASSERT_EQ(booleanArray->GetWithoutChecks(0), false);
434*795d594fSAndroid Build Coastguard Worker
435*795d594fSAndroid Build Coastguard Worker ArtField* byteArrayField = h_klass->FindDeclaredStaticField("byteArrayField", "[B");
436*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(byteArrayField != nullptr);
437*795d594fSAndroid Build Coastguard Worker Handle<mirror::ByteArray> byteArray =
438*795d594fSAndroid Build Coastguard Worker hs.NewHandle(byteArrayField->GetObject(h_klass.Get())->AsByteArray());
439*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(byteArray != nullptr);
440*795d594fSAndroid Build Coastguard Worker ASSERT_EQ(byteArray->GetLength(), 1);
441*795d594fSAndroid Build Coastguard Worker ASSERT_EQ(byteArray->GetWithoutChecks(0), 0);
442*795d594fSAndroid Build Coastguard Worker
443*795d594fSAndroid Build Coastguard Worker ArtField* charArrayField = h_klass->FindDeclaredStaticField("charArrayField", "[C");
444*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(charArrayField != nullptr);
445*795d594fSAndroid Build Coastguard Worker Handle<mirror::CharArray> charArray =
446*795d594fSAndroid Build Coastguard Worker hs.NewHandle(charArrayField->GetObject(h_klass.Get())->AsCharArray());
447*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(charArray != nullptr);
448*795d594fSAndroid Build Coastguard Worker ASSERT_EQ(charArray->GetLength(), 1);
449*795d594fSAndroid Build Coastguard Worker ASSERT_EQ(charArray->GetWithoutChecks(0), 0u);
450*795d594fSAndroid Build Coastguard Worker
451*795d594fSAndroid Build Coastguard Worker ArtField* shortArrayField = h_klass->FindDeclaredStaticField("shortArrayField", "[S");
452*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(shortArrayField != nullptr);
453*795d594fSAndroid Build Coastguard Worker Handle<mirror::ShortArray> shortArray =
454*795d594fSAndroid Build Coastguard Worker hs.NewHandle(shortArrayField->GetObject(h_klass.Get())->AsShortArray());
455*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(shortArray != nullptr);
456*795d594fSAndroid Build Coastguard Worker ASSERT_EQ(shortArray->GetLength(), 1);
457*795d594fSAndroid Build Coastguard Worker ASSERT_EQ(shortArray->GetWithoutChecks(0), 0);
458*795d594fSAndroid Build Coastguard Worker
459*795d594fSAndroid Build Coastguard Worker ArtField* intArrayField = h_klass->FindDeclaredStaticField("intArrayField", "[I");
460*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(intArrayField != nullptr);
461*795d594fSAndroid Build Coastguard Worker Handle<mirror::IntArray> intArray =
462*795d594fSAndroid Build Coastguard Worker hs.NewHandle(intArrayField->GetObject(h_klass.Get())->AsIntArray());
463*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(intArray != nullptr);
464*795d594fSAndroid Build Coastguard Worker ASSERT_EQ(intArray->GetLength(), 1);
465*795d594fSAndroid Build Coastguard Worker ASSERT_EQ(intArray->GetWithoutChecks(0), 0);
466*795d594fSAndroid Build Coastguard Worker
467*795d594fSAndroid Build Coastguard Worker ArtField* longArrayField = h_klass->FindDeclaredStaticField("longArrayField", "[J");
468*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(longArrayField != nullptr);
469*795d594fSAndroid Build Coastguard Worker Handle<mirror::LongArray> longArray =
470*795d594fSAndroid Build Coastguard Worker hs.NewHandle(longArrayField->GetObject(h_klass.Get())->AsLongArray());
471*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(longArray != nullptr);
472*795d594fSAndroid Build Coastguard Worker ASSERT_EQ(longArray->GetLength(), 1);
473*795d594fSAndroid Build Coastguard Worker ASSERT_EQ(longArray->GetWithoutChecks(0), static_cast<int64_t>(0));
474*795d594fSAndroid Build Coastguard Worker
475*795d594fSAndroid Build Coastguard Worker ArtField* floatArrayField = h_klass->FindDeclaredStaticField("floatArrayField", "[F");
476*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(floatArrayField != nullptr);
477*795d594fSAndroid Build Coastguard Worker Handle<mirror::FloatArray> floatArray =
478*795d594fSAndroid Build Coastguard Worker hs.NewHandle(floatArrayField->GetObject(h_klass.Get())->AsFloatArray());
479*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(floatArray != nullptr);
480*795d594fSAndroid Build Coastguard Worker ASSERT_EQ(floatArray->GetLength(), 1);
481*795d594fSAndroid Build Coastguard Worker ASSERT_FLOAT_EQ(floatArray->GetWithoutChecks(0), static_cast<float>(0.0f));
482*795d594fSAndroid Build Coastguard Worker
483*795d594fSAndroid Build Coastguard Worker ArtField* doubleArrayField = h_klass->FindDeclaredStaticField("doubleArrayField", "[D");
484*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(doubleArrayField != nullptr);
485*795d594fSAndroid Build Coastguard Worker Handle<mirror::DoubleArray> doubleArray =
486*795d594fSAndroid Build Coastguard Worker hs.NewHandle(doubleArrayField->GetObject(h_klass.Get())->AsDoubleArray());
487*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(doubleArray != nullptr);
488*795d594fSAndroid Build Coastguard Worker ASSERT_EQ(doubleArray->GetLength(), 1);
489*795d594fSAndroid Build Coastguard Worker ASSERT_DOUBLE_EQ(doubleArray->GetWithoutChecks(0), static_cast<double>(0.0f));
490*795d594fSAndroid Build Coastguard Worker
491*795d594fSAndroid Build Coastguard Worker ArtField* objectArrayField =
492*795d594fSAndroid Build Coastguard Worker h_klass->FindDeclaredStaticField("objectArrayField", "[Ljava/lang/Object;");
493*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(objectArrayField != nullptr);
494*795d594fSAndroid Build Coastguard Worker Handle<mirror::ObjectArray<mirror::Object>> objectArray =
495*795d594fSAndroid Build Coastguard Worker hs.NewHandle(objectArrayField->GetObject(h_klass.Get())->AsObjectArray<mirror::Object>());
496*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(objectArray != nullptr);
497*795d594fSAndroid Build Coastguard Worker ASSERT_EQ(objectArray->GetLength(), 1);
498*795d594fSAndroid Build Coastguard Worker ASSERT_EQ(objectArray->GetWithoutChecks(0), nullptr);
499*795d594fSAndroid Build Coastguard Worker
500*795d594fSAndroid Build Coastguard Worker // Create a java.lang.Object instance to set objectField.
501*795d594fSAndroid Build Coastguard Worker Handle<mirror::Class> object_klass(
502*795d594fSAndroid Build Coastguard Worker hs.NewHandle(class_linker_->FindSystemClass(soa.Self(), "Ljava/lang/Object;")));
503*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(object_klass != nullptr);
504*795d594fSAndroid Build Coastguard Worker Handle<mirror::Object> h_obj(hs.NewHandle(h_klass->AllocObject(soa.Self())));
505*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(h_obj != nullptr);
506*795d594fSAndroid Build Coastguard Worker ASSERT_OBJ_PTR_EQ(h_obj->GetClass(), h_klass.Get());
507*795d594fSAndroid Build Coastguard Worker
508*795d594fSAndroid Build Coastguard Worker // Modify fields inside transaction then rollback changes.
509*795d594fSAndroid Build Coastguard Worker EnterTransactionMode();
510*795d594fSAndroid Build Coastguard Worker booleanArray->SetWithoutChecks<true>(0, true);
511*795d594fSAndroid Build Coastguard Worker byteArray->SetWithoutChecks<true>(0, 1);
512*795d594fSAndroid Build Coastguard Worker charArray->SetWithoutChecks<true>(0, 1u);
513*795d594fSAndroid Build Coastguard Worker shortArray->SetWithoutChecks<true>(0, 1);
514*795d594fSAndroid Build Coastguard Worker intArray->SetWithoutChecks<true>(0, 1);
515*795d594fSAndroid Build Coastguard Worker longArray->SetWithoutChecks<true>(0, 1);
516*795d594fSAndroid Build Coastguard Worker floatArray->SetWithoutChecks<true>(0, 1.0);
517*795d594fSAndroid Build Coastguard Worker doubleArray->SetWithoutChecks<true>(0, 1.0);
518*795d594fSAndroid Build Coastguard Worker objectArray->SetWithoutChecks<true>(0, h_obj.Get());
519*795d594fSAndroid Build Coastguard Worker RollbackAndExitTransactionMode();
520*795d594fSAndroid Build Coastguard Worker
521*795d594fSAndroid Build Coastguard Worker // Check values have properly been restored to their original (default) value.
522*795d594fSAndroid Build Coastguard Worker EXPECT_EQ(booleanArray->GetWithoutChecks(0), false);
523*795d594fSAndroid Build Coastguard Worker EXPECT_EQ(byteArray->GetWithoutChecks(0), 0);
524*795d594fSAndroid Build Coastguard Worker EXPECT_EQ(charArray->GetWithoutChecks(0), 0u);
525*795d594fSAndroid Build Coastguard Worker EXPECT_EQ(shortArray->GetWithoutChecks(0), 0);
526*795d594fSAndroid Build Coastguard Worker EXPECT_EQ(intArray->GetWithoutChecks(0), 0);
527*795d594fSAndroid Build Coastguard Worker EXPECT_EQ(longArray->GetWithoutChecks(0), static_cast<int64_t>(0));
528*795d594fSAndroid Build Coastguard Worker EXPECT_FLOAT_EQ(floatArray->GetWithoutChecks(0), static_cast<float>(0.0f));
529*795d594fSAndroid Build Coastguard Worker EXPECT_DOUBLE_EQ(doubleArray->GetWithoutChecks(0), static_cast<double>(0.0f));
530*795d594fSAndroid Build Coastguard Worker EXPECT_EQ(objectArray->GetWithoutChecks(0), nullptr);
531*795d594fSAndroid Build Coastguard Worker }
532*795d594fSAndroid Build Coastguard Worker
533*795d594fSAndroid Build Coastguard Worker // Tests rolling back interned strings and resolved strings.
TEST_F(TransactionTest,ResolveString)534*795d594fSAndroid Build Coastguard Worker TEST_F(TransactionTest, ResolveString) {
535*795d594fSAndroid Build Coastguard Worker ScopedObjectAccess soa(Thread::Current());
536*795d594fSAndroid Build Coastguard Worker StackHandleScope<3> hs(soa.Self());
537*795d594fSAndroid Build Coastguard Worker Handle<mirror::ClassLoader> class_loader(
538*795d594fSAndroid Build Coastguard Worker hs.NewHandle(soa.Decode<mirror::ClassLoader>(LoadDex("Transaction"))));
539*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(class_loader != nullptr);
540*795d594fSAndroid Build Coastguard Worker
541*795d594fSAndroid Build Coastguard Worker Handle<mirror::Class> h_klass =
542*795d594fSAndroid Build Coastguard Worker hs.NewHandle(FindClass("LTransaction$ResolveString;", class_loader));
543*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(h_klass != nullptr);
544*795d594fSAndroid Build Coastguard Worker
545*795d594fSAndroid Build Coastguard Worker Handle<mirror::DexCache> h_dex_cache(hs.NewHandle(h_klass->GetDexCache()));
546*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(h_dex_cache != nullptr);
547*795d594fSAndroid Build Coastguard Worker const DexFile* const dex_file = h_dex_cache->GetDexFile();
548*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(dex_file != nullptr);
549*795d594fSAndroid Build Coastguard Worker
550*795d594fSAndroid Build Coastguard Worker // Go search the dex file to find the string id of our string.
551*795d594fSAndroid Build Coastguard Worker static const char* kResolvedString = "ResolvedString";
552*795d594fSAndroid Build Coastguard Worker const dex::StringId* string_id = dex_file->FindStringId(kResolvedString);
553*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(string_id != nullptr);
554*795d594fSAndroid Build Coastguard Worker dex::StringIndex string_idx = dex_file->GetIndexForStringId(*string_id);
555*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(string_idx.IsValid());
556*795d594fSAndroid Build Coastguard Worker // String should only get resolved by the initializer.
557*795d594fSAndroid Build Coastguard Worker EXPECT_TRUE(class_linker_->LookupString(string_idx, h_dex_cache.Get()) == nullptr);
558*795d594fSAndroid Build Coastguard Worker EXPECT_TRUE(h_dex_cache->GetResolvedString(string_idx) == nullptr);
559*795d594fSAndroid Build Coastguard Worker // Do the transaction, then roll back.
560*795d594fSAndroid Build Coastguard Worker EnterTransactionMode();
561*795d594fSAndroid Build Coastguard Worker bool success = class_linker_->EnsureInitialized(soa.Self(), h_klass, true, true);
562*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(success);
563*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(h_klass->IsInitialized());
564*795d594fSAndroid Build Coastguard Worker // Make sure the string got resolved by the transaction.
565*795d594fSAndroid Build Coastguard Worker {
566*795d594fSAndroid Build Coastguard Worker ObjPtr<mirror::String> s =
567*795d594fSAndroid Build Coastguard Worker class_linker_->LookupString(string_idx, h_dex_cache.Get());
568*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(s != nullptr);
569*795d594fSAndroid Build Coastguard Worker EXPECT_STREQ(s->ToModifiedUtf8().c_str(), kResolvedString);
570*795d594fSAndroid Build Coastguard Worker EXPECT_OBJ_PTR_EQ(s, h_dex_cache->GetResolvedString(string_idx));
571*795d594fSAndroid Build Coastguard Worker }
572*795d594fSAndroid Build Coastguard Worker RollbackAndExitTransactionMode();
573*795d594fSAndroid Build Coastguard Worker // Check that the string did not stay resolved.
574*795d594fSAndroid Build Coastguard Worker EXPECT_TRUE(class_linker_->LookupString(string_idx, h_dex_cache.Get()) == nullptr);
575*795d594fSAndroid Build Coastguard Worker EXPECT_TRUE(h_dex_cache->GetResolvedString(string_idx) == nullptr);
576*795d594fSAndroid Build Coastguard Worker ASSERT_FALSE(h_klass->IsInitialized());
577*795d594fSAndroid Build Coastguard Worker ASSERT_FALSE(soa.Self()->IsExceptionPending());
578*795d594fSAndroid Build Coastguard Worker }
579*795d594fSAndroid Build Coastguard Worker
580*795d594fSAndroid Build Coastguard Worker class MethodTypeTransactionTest : public TransactionTest {
581*795d594fSAndroid Build Coastguard Worker protected:
MethodTypeTransactionTest()582*795d594fSAndroid Build Coastguard Worker MethodTypeTransactionTest() {
583*795d594fSAndroid Build Coastguard Worker // java.lang.invoke.MethodType factory methods and mirror::MethodType::Create
584*795d594fSAndroid Build Coastguard Worker // are backed by the same cache, which is in the primary boot image. As as a
585*795d594fSAndroid Build Coastguard Worker // result, MethodType creation can lead to writes to the map under a
586*795d594fSAndroid Build Coastguard Worker // transaction, which is forbidden.
587*795d594fSAndroid Build Coastguard Worker this->use_boot_image_ = false;
588*795d594fSAndroid Build Coastguard Worker }
589*795d594fSAndroid Build Coastguard Worker };
590*795d594fSAndroid Build Coastguard Worker
591*795d594fSAndroid Build Coastguard Worker // Tests rolling back resolved method types in dex cache.
TEST_F(MethodTypeTransactionTest,ResolveMethodType)592*795d594fSAndroid Build Coastguard Worker TEST_F(MethodTypeTransactionTest, ResolveMethodType) {
593*795d594fSAndroid Build Coastguard Worker ScopedObjectAccess soa(Thread::Current());
594*795d594fSAndroid Build Coastguard Worker StackHandleScope<3> hs(soa.Self());
595*795d594fSAndroid Build Coastguard Worker Handle<mirror::ClassLoader> class_loader(
596*795d594fSAndroid Build Coastguard Worker hs.NewHandle(soa.Decode<mirror::ClassLoader>(LoadDex("Transaction"))));
597*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(class_loader != nullptr);
598*795d594fSAndroid Build Coastguard Worker
599*795d594fSAndroid Build Coastguard Worker MutableHandle<mirror::Class> h_klass(hs.NewHandle(
600*795d594fSAndroid Build Coastguard Worker class_linker_->FindSystemClass(soa.Self(), "Ljava/util/concurrent/ConcurrentHashMap$Node;")));
601*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(h_klass != nullptr);
602*795d594fSAndroid Build Coastguard Worker
603*795d594fSAndroid Build Coastguard Worker class_linker_->EnsureInitialized(soa.Self(), h_klass, true, true);
604*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(h_klass->IsInitialized());
605*795d594fSAndroid Build Coastguard Worker
606*795d594fSAndroid Build Coastguard Worker h_klass.Assign(FindClass("LTransaction;", class_loader));
607*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(h_klass != nullptr);
608*795d594fSAndroid Build Coastguard Worker
609*795d594fSAndroid Build Coastguard Worker Handle<mirror::DexCache> h_dex_cache(hs.NewHandle(h_klass->GetDexCache()));
610*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(h_dex_cache != nullptr);
611*795d594fSAndroid Build Coastguard Worker const DexFile* const dex_file = h_dex_cache->GetDexFile();
612*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(dex_file != nullptr);
613*795d594fSAndroid Build Coastguard Worker
614*795d594fSAndroid Build Coastguard Worker ASSERT_NE(dex_file->NumProtoIds(), 0u);
615*795d594fSAndroid Build Coastguard Worker dex::ProtoIndex proto_index(0u);
616*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(h_dex_cache->GetResolvedMethodType(proto_index) == nullptr);
617*795d594fSAndroid Build Coastguard Worker
618*795d594fSAndroid Build Coastguard Worker // Do the transaction, then roll back.
619*795d594fSAndroid Build Coastguard Worker EnterTransactionMode();
620*795d594fSAndroid Build Coastguard Worker ObjPtr<mirror::MethodType> method_type =
621*795d594fSAndroid Build Coastguard Worker class_linker_->ResolveMethodType(soa.Self(), proto_index, h_dex_cache, class_loader);
622*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(method_type != nullptr);
623*795d594fSAndroid Build Coastguard Worker // Make sure the method type was recorded in the dex cache.
624*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(h_dex_cache->GetResolvedMethodType(proto_index) == method_type);
625*795d594fSAndroid Build Coastguard Worker RollbackAndExitTransactionMode();
626*795d594fSAndroid Build Coastguard Worker // Check that the method type was removed from the dex cache.
627*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(h_dex_cache->GetResolvedMethodType(proto_index) == nullptr);
628*795d594fSAndroid Build Coastguard Worker }
629*795d594fSAndroid Build Coastguard Worker
630*795d594fSAndroid Build Coastguard Worker // Tests successful class initialization without class initializer.
TEST_F(TransactionTest,EmptyClass)631*795d594fSAndroid Build Coastguard Worker TEST_F(TransactionTest, EmptyClass) {
632*795d594fSAndroid Build Coastguard Worker ScopedObjectAccess soa(Thread::Current());
633*795d594fSAndroid Build Coastguard Worker StackHandleScope<2> hs(soa.Self());
634*795d594fSAndroid Build Coastguard Worker Handle<mirror::ClassLoader> class_loader(
635*795d594fSAndroid Build Coastguard Worker hs.NewHandle(soa.Decode<mirror::ClassLoader>(LoadDex("Transaction"))));
636*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(class_loader != nullptr);
637*795d594fSAndroid Build Coastguard Worker
638*795d594fSAndroid Build Coastguard Worker Handle<mirror::Class> h_klass =
639*795d594fSAndroid Build Coastguard Worker hs.NewHandle(FindClass("LTransaction$EmptyStatic;", class_loader));
640*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(h_klass != nullptr);
641*795d594fSAndroid Build Coastguard Worker class_linker_->VerifyClass(soa.Self(), /* verifier_deps= */ nullptr, h_klass);
642*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(h_klass->IsVerified());
643*795d594fSAndroid Build Coastguard Worker
644*795d594fSAndroid Build Coastguard Worker EnterTransactionMode();
645*795d594fSAndroid Build Coastguard Worker bool success = class_linker_->EnsureInitialized(soa.Self(), h_klass, true, true);
646*795d594fSAndroid Build Coastguard Worker ExitTransactionMode();
647*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(success);
648*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(h_klass->IsInitialized());
649*795d594fSAndroid Build Coastguard Worker ASSERT_FALSE(soa.Self()->IsExceptionPending());
650*795d594fSAndroid Build Coastguard Worker }
651*795d594fSAndroid Build Coastguard Worker
652*795d594fSAndroid Build Coastguard Worker // Tests successful class initialization with class initializer.
TEST_F(TransactionTest,StaticFieldClass)653*795d594fSAndroid Build Coastguard Worker TEST_F(TransactionTest, StaticFieldClass) {
654*795d594fSAndroid Build Coastguard Worker ScopedObjectAccess soa(Thread::Current());
655*795d594fSAndroid Build Coastguard Worker StackHandleScope<2> hs(soa.Self());
656*795d594fSAndroid Build Coastguard Worker Handle<mirror::ClassLoader> class_loader(
657*795d594fSAndroid Build Coastguard Worker hs.NewHandle(soa.Decode<mirror::ClassLoader>(LoadDex("Transaction"))));
658*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(class_loader != nullptr);
659*795d594fSAndroid Build Coastguard Worker
660*795d594fSAndroid Build Coastguard Worker Handle<mirror::Class> h_klass =
661*795d594fSAndroid Build Coastguard Worker hs.NewHandle(FindClass("LTransaction$StaticFieldClass;", class_loader));
662*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(h_klass != nullptr);
663*795d594fSAndroid Build Coastguard Worker class_linker_->VerifyClass(soa.Self(), /* verifier_deps= */ nullptr, h_klass);
664*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(h_klass->IsVerified());
665*795d594fSAndroid Build Coastguard Worker
666*795d594fSAndroid Build Coastguard Worker EnterTransactionMode();
667*795d594fSAndroid Build Coastguard Worker bool success = class_linker_->EnsureInitialized(soa.Self(), h_klass, true, true);
668*795d594fSAndroid Build Coastguard Worker ExitTransactionMode();
669*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(success);
670*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(h_klass->IsInitialized());
671*795d594fSAndroid Build Coastguard Worker ASSERT_FALSE(soa.Self()->IsExceptionPending());
672*795d594fSAndroid Build Coastguard Worker }
673*795d594fSAndroid Build Coastguard Worker
674*795d594fSAndroid Build Coastguard Worker // Tests failing class initialization due to native call.
TEST_F(TransactionTest,NativeCallAbortClass)675*795d594fSAndroid Build Coastguard Worker TEST_F(TransactionTest, NativeCallAbortClass) {
676*795d594fSAndroid Build Coastguard Worker testTransactionAbort("LTransaction$NativeCallAbortClass;");
677*795d594fSAndroid Build Coastguard Worker }
678*795d594fSAndroid Build Coastguard Worker
679*795d594fSAndroid Build Coastguard Worker // Tests failing class initialization due to native call in a "synchronized" statement
680*795d594fSAndroid Build Coastguard Worker // (which must catch any exception, do the monitor-exit then re-throw the caught exception).
TEST_F(TransactionTest,SynchronizedNativeCallAbortClass)681*795d594fSAndroid Build Coastguard Worker TEST_F(TransactionTest, SynchronizedNativeCallAbortClass) {
682*795d594fSAndroid Build Coastguard Worker testTransactionAbort("LTransaction$SynchronizedNativeCallAbortClass;");
683*795d594fSAndroid Build Coastguard Worker }
684*795d594fSAndroid Build Coastguard Worker
685*795d594fSAndroid Build Coastguard Worker // Tests failing class initialization due to native call, even if an "all" catch handler
686*795d594fSAndroid Build Coastguard Worker // catches the exception thrown when aborting the transaction.
TEST_F(TransactionTest,CatchNativeCallAbortClass)687*795d594fSAndroid Build Coastguard Worker TEST_F(TransactionTest, CatchNativeCallAbortClass) {
688*795d594fSAndroid Build Coastguard Worker testTransactionAbort("LTransaction$CatchNativeCallAbortClass;");
689*795d594fSAndroid Build Coastguard Worker }
690*795d594fSAndroid Build Coastguard Worker
691*795d594fSAndroid Build Coastguard Worker // Tests failing class initialization with multiple transaction aborts.
TEST_F(TransactionTest,MultipleNativeCallAbortClass)692*795d594fSAndroid Build Coastguard Worker TEST_F(TransactionTest, MultipleNativeCallAbortClass) {
693*795d594fSAndroid Build Coastguard Worker testTransactionAbort("LTransaction$MultipleNativeCallAbortClass;");
694*795d594fSAndroid Build Coastguard Worker }
695*795d594fSAndroid Build Coastguard Worker
696*795d594fSAndroid Build Coastguard Worker // Tests failing class initialization due to Class.forName() not finding the class,
697*795d594fSAndroid Build Coastguard Worker // even if an "all" catch handler catches the exception thrown when aborting the transaction.
TEST_F(TransactionTest,CatchClassForNameAbortClass)698*795d594fSAndroid Build Coastguard Worker TEST_F(TransactionTest, CatchClassForNameAbortClass) {
699*795d594fSAndroid Build Coastguard Worker testTransactionAbort("LTransaction$CatchClassForNameAbortClass;");
700*795d594fSAndroid Build Coastguard Worker }
701*795d594fSAndroid Build Coastguard Worker
702*795d594fSAndroid Build Coastguard Worker // Same as CatchClassForNameAbortClass but the class initializer tries to do the work twice.
703*795d594fSAndroid Build Coastguard Worker // This would trigger a DCHECK() if we continued executing bytecode with an aborted transaction.
TEST_F(TransactionTest,CatchClassForNameAbortClassTwice)704*795d594fSAndroid Build Coastguard Worker TEST_F(TransactionTest, CatchClassForNameAbortClassTwice) {
705*795d594fSAndroid Build Coastguard Worker testTransactionAbort("LTransaction$CatchClassForNameAbortClassTwice;");
706*795d594fSAndroid Build Coastguard Worker }
707*795d594fSAndroid Build Coastguard Worker
708*795d594fSAndroid Build Coastguard Worker // Tests failing class initialization due to allocating instance of finalizable class.
TEST_F(TransactionTest,FinalizableAbortClass)709*795d594fSAndroid Build Coastguard Worker TEST_F(TransactionTest, FinalizableAbortClass) {
710*795d594fSAndroid Build Coastguard Worker testTransactionAbort("LTransaction$FinalizableAbortClass;");
711*795d594fSAndroid Build Coastguard Worker }
712*795d594fSAndroid Build Coastguard Worker
TEST_F(TransactionTest,Constraints)713*795d594fSAndroid Build Coastguard Worker TEST_F(TransactionTest, Constraints) {
714*795d594fSAndroid Build Coastguard Worker ScopedObjectAccess soa(Thread::Current());
715*795d594fSAndroid Build Coastguard Worker StackHandleScope<11> hs(soa.Self());
716*795d594fSAndroid Build Coastguard Worker Handle<mirror::ClassLoader> class_loader(
717*795d594fSAndroid Build Coastguard Worker hs.NewHandle(soa.Decode<mirror::ClassLoader>(LoadDex("Transaction"))));
718*795d594fSAndroid Build Coastguard Worker
719*795d594fSAndroid Build Coastguard Worker gc::Heap* heap = Runtime::Current()->GetHeap();
720*795d594fSAndroid Build Coastguard Worker Handle<mirror::Class> boolean_class =
721*795d594fSAndroid Build Coastguard Worker hs.NewHandle(FindClass("Ljava/lang/Boolean;", class_loader));
722*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(boolean_class != nullptr);
723*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(heap->ObjectIsInBootImageSpace(boolean_class.Get()));
724*795d594fSAndroid Build Coastguard Worker ArtField* true_field = boolean_class->FindDeclaredStaticField("TRUE", "Ljava/lang/Boolean;");
725*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(true_field != nullptr);
726*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(true_field->IsStatic());
727*795d594fSAndroid Build Coastguard Worker Handle<mirror::Object> true_value = hs.NewHandle(true_field->GetObject(boolean_class.Get()));
728*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(true_value != nullptr);
729*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(heap->ObjectIsInBootImageSpace(true_value.Get()));
730*795d594fSAndroid Build Coastguard Worker ArtField* value_field = boolean_class->FindDeclaredInstanceField("value", "Z");
731*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(value_field != nullptr);
732*795d594fSAndroid Build Coastguard Worker ASSERT_FALSE(value_field->IsStatic());
733*795d594fSAndroid Build Coastguard Worker
734*795d594fSAndroid Build Coastguard Worker Handle<mirror::Class> static_field_class =
735*795d594fSAndroid Build Coastguard Worker hs.NewHandle(FindClass("LTransaction$StaticFieldClass;", class_loader));
736*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(static_field_class != nullptr);
737*795d594fSAndroid Build Coastguard Worker ASSERT_FALSE(heap->ObjectIsInBootImageSpace(static_field_class.Get()));
738*795d594fSAndroid Build Coastguard Worker ArtField* int_field = static_field_class->FindDeclaredStaticField("intField", "I");
739*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(int_field != nullptr);
740*795d594fSAndroid Build Coastguard Worker
741*795d594fSAndroid Build Coastguard Worker Handle<mirror::Class> static_fields_test_class =
742*795d594fSAndroid Build Coastguard Worker hs.NewHandle(FindClass("LStaticFieldsTest;", class_loader));
743*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(static_fields_test_class != nullptr);
744*795d594fSAndroid Build Coastguard Worker ASSERT_FALSE(heap->ObjectIsInBootImageSpace(static_fields_test_class.Get()));
745*795d594fSAndroid Build Coastguard Worker ArtField* static_fields_test_int_field =
746*795d594fSAndroid Build Coastguard Worker static_fields_test_class->FindDeclaredStaticField("intField", "I");
747*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(static_fields_test_int_field != nullptr);
748*795d594fSAndroid Build Coastguard Worker
749*795d594fSAndroid Build Coastguard Worker Handle<mirror::Class> instance_fields_test_class =
750*795d594fSAndroid Build Coastguard Worker hs.NewHandle(FindClass("LInstanceFieldsTest;", class_loader));
751*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(instance_fields_test_class != nullptr);
752*795d594fSAndroid Build Coastguard Worker ASSERT_FALSE(heap->ObjectIsInBootImageSpace(instance_fields_test_class.Get()));
753*795d594fSAndroid Build Coastguard Worker ArtField* instance_fields_test_int_field =
754*795d594fSAndroid Build Coastguard Worker instance_fields_test_class->FindDeclaredInstanceField("intField", "I");
755*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(instance_fields_test_int_field != nullptr);
756*795d594fSAndroid Build Coastguard Worker Handle<mirror::Object> instance_fields_test_object = hs.NewHandle(
757*795d594fSAndroid Build Coastguard Worker instance_fields_test_class->Alloc(soa.Self(), heap->GetCurrentAllocator()));
758*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(instance_fields_test_object != nullptr);
759*795d594fSAndroid Build Coastguard Worker ASSERT_FALSE(heap->ObjectIsInBootImageSpace(instance_fields_test_object.Get()));
760*795d594fSAndroid Build Coastguard Worker
761*795d594fSAndroid Build Coastguard Worker // The `long[].class` should be in the boot image but `long[][][].class` should not.
762*795d594fSAndroid Build Coastguard Worker // (We have seen `long[][].class` both present and missing from the boot image,
763*795d594fSAndroid Build Coastguard Worker // depending on the libcore code, so we do not use it for this test.)
764*795d594fSAndroid Build Coastguard Worker Handle<mirror::Class> long_array_dim3_class = hs.NewHandle(FindClass("[[[J", class_loader));
765*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(long_array_dim3_class != nullptr);
766*795d594fSAndroid Build Coastguard Worker ASSERT_FALSE(heap->ObjectIsInBootImageSpace(long_array_dim3_class.Get()));
767*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(heap->ObjectIsInBootImageSpace(
768*795d594fSAndroid Build Coastguard Worker long_array_dim3_class->GetComponentType()->GetComponentType()));
769*795d594fSAndroid Build Coastguard Worker Handle<mirror::Array> long_array_dim3 = hs.NewHandle(mirror::Array::Alloc(
770*795d594fSAndroid Build Coastguard Worker soa.Self(),
771*795d594fSAndroid Build Coastguard Worker long_array_dim3_class.Get(),
772*795d594fSAndroid Build Coastguard Worker /*component_count=*/ 1,
773*795d594fSAndroid Build Coastguard Worker long_array_dim3_class->GetComponentSizeShift(),
774*795d594fSAndroid Build Coastguard Worker heap->GetCurrentAllocator()));
775*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(long_array_dim3 != nullptr);
776*795d594fSAndroid Build Coastguard Worker ASSERT_FALSE(heap->ObjectIsInBootImageSpace(long_array_dim3.Get()));
777*795d594fSAndroid Build Coastguard Worker Handle<mirror::Array> long_array = hs.NewHandle(mirror::Array::Alloc(
778*795d594fSAndroid Build Coastguard Worker soa.Self(),
779*795d594fSAndroid Build Coastguard Worker long_array_dim3_class->GetComponentType()->GetComponentType(),
780*795d594fSAndroid Build Coastguard Worker /*component_count=*/ 1,
781*795d594fSAndroid Build Coastguard Worker long_array_dim3_class->GetComponentType()->GetComponentType()->GetComponentSizeShift(),
782*795d594fSAndroid Build Coastguard Worker heap->GetCurrentAllocator()));
783*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(long_array != nullptr);
784*795d594fSAndroid Build Coastguard Worker ASSERT_FALSE(heap->ObjectIsInBootImageSpace(long_array.Get()));
785*795d594fSAndroid Build Coastguard Worker
786*795d594fSAndroid Build Coastguard Worker // Use the Array's IfTable as an array from the boot image.
787*795d594fSAndroid Build Coastguard Worker Handle<mirror::ObjectArray<mirror::Object>> array_iftable =
788*795d594fSAndroid Build Coastguard Worker hs.NewHandle(long_array_dim3_class->GetIfTable());
789*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(array_iftable != nullptr);
790*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(heap->ObjectIsInBootImageSpace(array_iftable.Get()));
791*795d594fSAndroid Build Coastguard Worker
792*795d594fSAndroid Build Coastguard Worker // Test non-strict transaction.
793*795d594fSAndroid Build Coastguard Worker ArenaPool* arena_pool = Runtime::Current()->GetArenaPool();
794*795d594fSAndroid Build Coastguard Worker Transaction transaction(
795*795d594fSAndroid Build Coastguard Worker /*strict=*/ false, /*root=*/ nullptr, /*arena_stack=*/ nullptr, arena_pool);
796*795d594fSAndroid Build Coastguard Worker // Static field in boot image.
797*795d594fSAndroid Build Coastguard Worker EXPECT_TRUE(transaction.WriteConstraint(boolean_class.Get()));
798*795d594fSAndroid Build Coastguard Worker EXPECT_FALSE(transaction.ReadConstraint(boolean_class.Get()));
799*795d594fSAndroid Build Coastguard Worker // Instance field or array element in boot image.
800*795d594fSAndroid Build Coastguard Worker // Do not check ReadConstraint(), it expects only static fields (checks for class object).
801*795d594fSAndroid Build Coastguard Worker EXPECT_TRUE(transaction.WriteConstraint(true_value.Get()));
802*795d594fSAndroid Build Coastguard Worker EXPECT_TRUE(transaction.WriteConstraint(array_iftable.Get()));
803*795d594fSAndroid Build Coastguard Worker // Static field not in boot image.
804*795d594fSAndroid Build Coastguard Worker EXPECT_FALSE(transaction.WriteConstraint(static_fields_test_class.Get()));
805*795d594fSAndroid Build Coastguard Worker EXPECT_FALSE(transaction.ReadConstraint(static_fields_test_class.Get()));
806*795d594fSAndroid Build Coastguard Worker // Instance field or array element not in boot image.
807*795d594fSAndroid Build Coastguard Worker // Do not check ReadConstraint(), it expects only static fields (checks for class object).
808*795d594fSAndroid Build Coastguard Worker EXPECT_FALSE(transaction.WriteConstraint(instance_fields_test_object.Get()));
809*795d594fSAndroid Build Coastguard Worker EXPECT_FALSE(transaction.WriteConstraint(long_array_dim3.Get()));
810*795d594fSAndroid Build Coastguard Worker // Write value constraints.
811*795d594fSAndroid Build Coastguard Worker EXPECT_FALSE(transaction.WriteValueConstraint(static_fields_test_class.Get()));
812*795d594fSAndroid Build Coastguard Worker EXPECT_FALSE(transaction.WriteValueConstraint(instance_fields_test_object.Get()));
813*795d594fSAndroid Build Coastguard Worker EXPECT_TRUE(transaction.WriteValueConstraint(long_array_dim3->GetClass()));
814*795d594fSAndroid Build Coastguard Worker EXPECT_TRUE(transaction.WriteValueConstraint(long_array_dim3.Get()));
815*795d594fSAndroid Build Coastguard Worker EXPECT_FALSE(transaction.WriteValueConstraint(long_array->GetClass()));
816*795d594fSAndroid Build Coastguard Worker EXPECT_FALSE(transaction.WriteValueConstraint(long_array.Get()));
817*795d594fSAndroid Build Coastguard Worker
818*795d594fSAndroid Build Coastguard Worker // Test strict transaction.
819*795d594fSAndroid Build Coastguard Worker Transaction strict_transaction(
820*795d594fSAndroid Build Coastguard Worker /*strict=*/ true, /*root=*/ static_field_class.Get(), /*arena_stack=*/ nullptr, arena_pool);
821*795d594fSAndroid Build Coastguard Worker // Static field in boot image.
822*795d594fSAndroid Build Coastguard Worker EXPECT_TRUE(strict_transaction.WriteConstraint(boolean_class.Get()));
823*795d594fSAndroid Build Coastguard Worker EXPECT_TRUE(strict_transaction.ReadConstraint(boolean_class.Get()));
824*795d594fSAndroid Build Coastguard Worker // Instance field or array element in boot image.
825*795d594fSAndroid Build Coastguard Worker // Do not check ReadConstraint(), it expects only static fields (checks for class object).
826*795d594fSAndroid Build Coastguard Worker EXPECT_TRUE(strict_transaction.WriteConstraint(true_value.Get()));
827*795d594fSAndroid Build Coastguard Worker EXPECT_TRUE(strict_transaction.WriteConstraint(array_iftable.Get()));
828*795d594fSAndroid Build Coastguard Worker // Static field in another class not in boot image.
829*795d594fSAndroid Build Coastguard Worker EXPECT_TRUE(strict_transaction.WriteConstraint(static_fields_test_class.Get()));
830*795d594fSAndroid Build Coastguard Worker EXPECT_TRUE(strict_transaction.ReadConstraint(static_fields_test_class.Get()));
831*795d594fSAndroid Build Coastguard Worker // Instance field or array element not in boot image.
832*795d594fSAndroid Build Coastguard Worker // Do not check ReadConstraint(), it expects only static fields (checks for class object).
833*795d594fSAndroid Build Coastguard Worker EXPECT_FALSE(strict_transaction.WriteConstraint(instance_fields_test_object.Get()));
834*795d594fSAndroid Build Coastguard Worker EXPECT_FALSE(strict_transaction.WriteConstraint(long_array_dim3.Get()));
835*795d594fSAndroid Build Coastguard Worker // Static field in the same class.
836*795d594fSAndroid Build Coastguard Worker EXPECT_FALSE(strict_transaction.WriteConstraint(static_field_class.Get()));
837*795d594fSAndroid Build Coastguard Worker EXPECT_FALSE(strict_transaction.ReadConstraint(static_field_class.Get()));
838*795d594fSAndroid Build Coastguard Worker // Write value constraints.
839*795d594fSAndroid Build Coastguard Worker EXPECT_FALSE(strict_transaction.WriteValueConstraint(static_fields_test_class.Get()));
840*795d594fSAndroid Build Coastguard Worker EXPECT_FALSE(strict_transaction.WriteValueConstraint(instance_fields_test_object.Get()));
841*795d594fSAndroid Build Coastguard Worker // TODO: The following may be revised, see a TODO in Transaction::WriteValueConstraint().
842*795d594fSAndroid Build Coastguard Worker EXPECT_FALSE(strict_transaction.WriteValueConstraint(long_array_dim3->GetClass()));
843*795d594fSAndroid Build Coastguard Worker EXPECT_FALSE(strict_transaction.WriteValueConstraint(long_array_dim3.Get()));
844*795d594fSAndroid Build Coastguard Worker EXPECT_FALSE(strict_transaction.WriteValueConstraint(long_array->GetClass()));
845*795d594fSAndroid Build Coastguard Worker EXPECT_FALSE(strict_transaction.WriteValueConstraint(long_array.Get()));
846*795d594fSAndroid Build Coastguard Worker }
847*795d594fSAndroid Build Coastguard Worker
848*795d594fSAndroid Build Coastguard Worker } // namespace art
849