xref: /aosp_15_r20/art/runtime/handle_scope_test.cc (revision 795d594fd825385562da6b089ea9b2033f3abf5a)
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 <type_traits>
18*795d594fSAndroid Build Coastguard Worker 
19*795d594fSAndroid Build Coastguard Worker #include "base/pointer_size.h"
20*795d594fSAndroid Build Coastguard Worker #include "class_linker-inl.h"
21*795d594fSAndroid Build Coastguard Worker #include "common_runtime_test.h"
22*795d594fSAndroid Build Coastguard Worker #include "gtest/gtest.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-alloc-inl.h"
26*795d594fSAndroid Build Coastguard Worker #include "mirror/class-inl.h"
27*795d594fSAndroid Build Coastguard Worker #include "mirror/object.h"
28*795d594fSAndroid Build Coastguard Worker #include "scoped_thread_state_change-inl.h"
29*795d594fSAndroid Build Coastguard Worker #include "thread.h"
30*795d594fSAndroid Build Coastguard Worker 
31*795d594fSAndroid Build Coastguard Worker namespace art HIDDEN {
32*795d594fSAndroid Build Coastguard Worker 
33*795d594fSAndroid Build Coastguard Worker // Handles are value objects and should be trivially copyable.
34*795d594fSAndroid Build Coastguard Worker static_assert(std::is_trivially_copyable<Handle<mirror::Object>>::value,
35*795d594fSAndroid Build Coastguard Worker               "Handle should be trivially copyable");
36*795d594fSAndroid Build Coastguard Worker static_assert(std::is_trivially_copyable<MutableHandle<mirror::Object>>::value,
37*795d594fSAndroid Build Coastguard Worker               "MutableHandle should be trivially copyable");
38*795d594fSAndroid Build Coastguard Worker static_assert(std::is_trivially_copyable<ScopedNullHandle<mirror::Object>>::value,
39*795d594fSAndroid Build Coastguard Worker               "ScopedNullHandle should be trivially copyable");
40*795d594fSAndroid Build Coastguard Worker 
41*795d594fSAndroid Build Coastguard Worker class HandleScopeTest : public CommonRuntimeTest {
42*795d594fSAndroid Build Coastguard Worker  protected:
HandleScopeTest()43*795d594fSAndroid Build Coastguard Worker   HandleScopeTest() {
44*795d594fSAndroid Build Coastguard Worker     use_boot_image_ = true;  // Make the Runtime creation cheaper.
45*795d594fSAndroid Build Coastguard Worker   }
46*795d594fSAndroid Build Coastguard Worker };
47*795d594fSAndroid Build Coastguard Worker 
48*795d594fSAndroid Build Coastguard Worker // Test the offsets computed for members of HandleScope. Because of cross-compiling
49*795d594fSAndroid Build Coastguard Worker // it is impossible the use OFFSETOF_MEMBER, so we do some reasonable computations ourselves. This
50*795d594fSAndroid Build Coastguard Worker // test checks whether we do the right thing.
TEST_F(HandleScopeTest,Offsets)51*795d594fSAndroid Build Coastguard Worker TEST_F(HandleScopeTest, Offsets) {
52*795d594fSAndroid Build Coastguard Worker   ScopedObjectAccess soa(Thread::Current());
53*795d594fSAndroid Build Coastguard Worker   ClassLinker* const class_linker = Runtime::Current()->GetClassLinker();
54*795d594fSAndroid Build Coastguard Worker   // As the members of HandleScope are private, we cannot use OFFSETOF_MEMBER
55*795d594fSAndroid Build Coastguard Worker   // here. So do the inverse: set some data, and access it through pointers created from the offsets.
56*795d594fSAndroid Build Coastguard Worker   StackHandleScope<0x1> hs0(soa.Self());
57*795d594fSAndroid Build Coastguard Worker   static const size_t kNumReferences = 0x9ABC;
58*795d594fSAndroid Build Coastguard Worker   StackHandleScope<kNumReferences> test_table(soa.Self());
59*795d594fSAndroid Build Coastguard Worker   ObjPtr<mirror::Class> c = class_linker->FindSystemClass(soa.Self(), "Ljava/lang/Object;");
60*795d594fSAndroid Build Coastguard Worker   test_table.NewHandle(c);
61*795d594fSAndroid Build Coastguard Worker 
62*795d594fSAndroid Build Coastguard Worker   uint8_t* table_base_ptr = reinterpret_cast<uint8_t*>(&test_table);
63*795d594fSAndroid Build Coastguard Worker 
64*795d594fSAndroid Build Coastguard Worker   {
65*795d594fSAndroid Build Coastguard Worker     BaseHandleScope** link_ptr = reinterpret_cast<BaseHandleScope**>(table_base_ptr +
66*795d594fSAndroid Build Coastguard Worker         HandleScope::LinkOffset(kRuntimePointerSize));
67*795d594fSAndroid Build Coastguard Worker     EXPECT_EQ(*link_ptr, &hs0);
68*795d594fSAndroid Build Coastguard Worker   }
69*795d594fSAndroid Build Coastguard Worker 
70*795d594fSAndroid Build Coastguard Worker   {
71*795d594fSAndroid Build Coastguard Worker     uint32_t* num_ptr = reinterpret_cast<uint32_t*>(
72*795d594fSAndroid Build Coastguard Worker         table_base_ptr + HandleScope::CapacityOffset(kRuntimePointerSize));
73*795d594fSAndroid Build Coastguard Worker     EXPECT_EQ(*num_ptr, static_cast<size_t>(kNumReferences));
74*795d594fSAndroid Build Coastguard Worker   }
75*795d594fSAndroid Build Coastguard Worker 
76*795d594fSAndroid Build Coastguard Worker   {
77*795d594fSAndroid Build Coastguard Worker     auto* ref_ptr = reinterpret_cast<StackReference<mirror::Object>*>(table_base_ptr +
78*795d594fSAndroid Build Coastguard Worker         HandleScope::ReferencesOffset(kRuntimePointerSize));
79*795d594fSAndroid Build Coastguard Worker     EXPECT_OBJ_PTR_EQ(ref_ptr->AsMirrorPtr(), c);
80*795d594fSAndroid Build Coastguard Worker   }
81*795d594fSAndroid Build Coastguard Worker }
82*795d594fSAndroid Build Coastguard Worker 
83*795d594fSAndroid Build Coastguard Worker class CollectVisitor {
84*795d594fSAndroid Build Coastguard Worker  public:
VisitRootIfNonNull(StackReference<mirror::Object> * ref)85*795d594fSAndroid Build Coastguard Worker   void VisitRootIfNonNull(StackReference<mirror::Object>* ref) {
86*795d594fSAndroid Build Coastguard Worker     if (!ref->IsNull()) {
87*795d594fSAndroid Build Coastguard Worker       visited.insert(ref);
88*795d594fSAndroid Build Coastguard Worker     }
89*795d594fSAndroid Build Coastguard Worker     ++total_visited;
90*795d594fSAndroid Build Coastguard Worker   }
91*795d594fSAndroid Build Coastguard Worker 
92*795d594fSAndroid Build Coastguard Worker   std::set<StackReference<mirror::Object>*> visited;
93*795d594fSAndroid Build Coastguard Worker   size_t total_visited = 0;  // including null.
94*795d594fSAndroid Build Coastguard Worker };
95*795d594fSAndroid Build Coastguard Worker 
96*795d594fSAndroid Build Coastguard Worker // Test functionality of variable sized handle scopes.
TEST_F(HandleScopeTest,VariableSized)97*795d594fSAndroid Build Coastguard Worker TEST_F(HandleScopeTest, VariableSized) {
98*795d594fSAndroid Build Coastguard Worker   ScopedObjectAccess soa(Thread::Current());
99*795d594fSAndroid Build Coastguard Worker   VariableSizedHandleScope hs(soa.Self());
100*795d594fSAndroid Build Coastguard Worker   std::vector<Handle<mirror::Object>> handles;
101*795d594fSAndroid Build Coastguard Worker   ClassLinker* const class_linker = Runtime::Current()->GetClassLinker();
102*795d594fSAndroid Build Coastguard Worker   Handle<mirror::Class> c =
103*795d594fSAndroid Build Coastguard Worker       hs.NewHandle(class_linker->FindSystemClass(soa.Self(), "Ljava/lang/Object;"));
104*795d594fSAndroid Build Coastguard Worker   handles.push_back(c);
105*795d594fSAndroid Build Coastguard Worker   // Test nested scopes.
106*795d594fSAndroid Build Coastguard Worker   StackHandleScope<1> inner(soa.Self());
107*795d594fSAndroid Build Coastguard Worker   inner.NewHandle(c->AllocObject(soa.Self()));
108*795d594fSAndroid Build Coastguard Worker   // Add a bunch of handles and make sure callbacks work.
109*795d594fSAndroid Build Coastguard Worker   static const size_t kNumHandles = 100;
110*795d594fSAndroid Build Coastguard Worker   for (size_t i = 0; i < kNumHandles; ++i) {
111*795d594fSAndroid Build Coastguard Worker     BaseHandleScope* base = &hs;
112*795d594fSAndroid Build Coastguard Worker     ObjPtr<mirror::Object> o = c->AllocObject(soa.Self());
113*795d594fSAndroid Build Coastguard Worker     handles.push_back(hs.NewHandle(o));
114*795d594fSAndroid Build Coastguard Worker     EXPECT_OBJ_PTR_EQ(o, handles.back().Get());
115*795d594fSAndroid Build Coastguard Worker     EXPECT_TRUE(hs.Contains(handles.back().GetReference()));
116*795d594fSAndroid Build Coastguard Worker     EXPECT_TRUE(base->Contains(handles.back().GetReference()));
117*795d594fSAndroid Build Coastguard Worker     EXPECT_EQ(hs.Capacity(), base->Capacity());
118*795d594fSAndroid Build Coastguard Worker   }
119*795d594fSAndroid Build Coastguard Worker   // Add one null handle.
120*795d594fSAndroid Build Coastguard Worker   Handle<mirror::Object> null_handle = hs.NewHandle<mirror::Object>(nullptr);
121*795d594fSAndroid Build Coastguard Worker   handles.push_back(null_handle);
122*795d594fSAndroid Build Coastguard Worker   CollectVisitor visitor;
123*795d594fSAndroid Build Coastguard Worker   BaseHandleScope* base = &hs;
124*795d594fSAndroid Build Coastguard Worker   base->VisitRoots(visitor);
125*795d594fSAndroid Build Coastguard Worker   EXPECT_EQ(visitor.visited.size() + /* null handle */ 1u, base->Size());
126*795d594fSAndroid Build Coastguard Worker   EXPECT_EQ(visitor.total_visited, base->Size());
127*795d594fSAndroid Build Coastguard Worker   for (StackReference<mirror::Object>* ref : visitor.visited) {
128*795d594fSAndroid Build Coastguard Worker     EXPECT_TRUE(base->Contains(ref));
129*795d594fSAndroid Build Coastguard Worker   }
130*795d594fSAndroid Build Coastguard Worker   // Test `VariableSizedHandleScope::GetHandle<.>()`.
131*795d594fSAndroid Build Coastguard Worker   for (size_t i = 0, size = handles.size(); i != size; ++i) {
132*795d594fSAndroid Build Coastguard Worker     EXPECT_EQ(handles[i].GetReference(), hs.GetHandle<mirror::Object>(i).GetReference());
133*795d594fSAndroid Build Coastguard Worker   }
134*795d594fSAndroid Build Coastguard Worker }
135*795d594fSAndroid Build Coastguard Worker 
136*795d594fSAndroid Build Coastguard Worker }  // namespace art
137