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