handle_scope_test.cc revision e8a3c576301fd531d5f73a65fc8b84a63619d580
1/* 2 * Copyright (C) 2014 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17#include "base/enums.h" 18#include "common_runtime_test.h" 19#include "gtest/gtest.h" 20#include "handle_scope-inl.h" 21#include "scoped_thread_state_change-inl.h" 22#include "thread.h" 23 24namespace art { 25 26class HandleScopeTest : public CommonRuntimeTest {}; 27 28// Test the offsets computed for members of HandleScope. Because of cross-compiling 29// it is impossible the use OFFSETOF_MEMBER, so we do some reasonable computations ourselves. This 30// test checks whether we do the right thing. 31TEST_F(HandleScopeTest, Offsets) { 32 ScopedObjectAccess soa(Thread::Current()); 33 ClassLinker* const class_linker = Runtime::Current()->GetClassLinker(); 34 // As the members of HandleScope are private, we cannot use OFFSETOF_MEMBER 35 // here. So do the inverse: set some data, and access it through pointers created from the offsets. 36 StackHandleScope<0x1> hs0(soa.Self()); 37 static const size_t kNumReferences = 0x9ABC; 38 StackHandleScope<kNumReferences> test_table(soa.Self()); 39 ObjPtr<mirror::Class> c = class_linker->FindSystemClass(soa.Self(), "Ljava/lang/Object;"); 40 test_table.SetReference(0, c.Ptr()); 41 42 uint8_t* table_base_ptr = reinterpret_cast<uint8_t*>(&test_table); 43 44 { 45 BaseHandleScope** link_ptr = reinterpret_cast<BaseHandleScope**>(table_base_ptr + 46 HandleScope::LinkOffset(kRuntimePointerSize)); 47 EXPECT_EQ(*link_ptr, &hs0); 48 } 49 50 { 51 uint32_t* num_ptr = reinterpret_cast<uint32_t*>(table_base_ptr + 52 HandleScope::NumberOfReferencesOffset(kRuntimePointerSize)); 53 EXPECT_EQ(*num_ptr, static_cast<size_t>(kNumReferences)); 54 } 55 56 { 57 auto* ref_ptr = reinterpret_cast<StackReference<mirror::Object>*>(table_base_ptr + 58 HandleScope::ReferencesOffset(kRuntimePointerSize)); 59 EXPECT_OBJ_PTR_EQ(ref_ptr->AsMirrorPtr(), c); 60 } 61} 62 63class CollectVisitor { 64 public: 65 void VisitRootIfNonNull(StackReference<mirror::Object>* ref) { 66 if (!ref->IsNull()) { 67 visited.insert(ref); 68 } 69 ++total_visited; 70 } 71 72 std::set<StackReference<mirror::Object>*> visited; 73 size_t total_visited = 0; // including null. 74}; 75 76// Test functionality of variable sized handle scopes. 77TEST_F(HandleScopeTest, VariableSized) { 78 ScopedObjectAccess soa(Thread::Current()); 79 VariableSizedHandleScope hs(soa.Self()); 80 ClassLinker* const class_linker = Runtime::Current()->GetClassLinker(); 81 Handle<mirror::Class> c = 82 hs.NewHandle(class_linker->FindSystemClass(soa.Self(), "Ljava/lang/Object;")); 83 // Test nested scopes. 84 StackHandleScope<1> inner(soa.Self()); 85 inner.NewHandle(c->AllocObject(soa.Self())); 86 // Add a bunch of handles and make sure callbacks work. 87 static const size_t kNumHandles = 100; 88 std::vector<Handle<mirror::Object>> handles; 89 for (size_t i = 0; i < kNumHandles; ++i) { 90 BaseHandleScope* base = &hs; 91 ObjPtr<mirror::Object> o = c->AllocObject(soa.Self()); 92 handles.push_back(hs.NewHandle(o)); 93 EXPECT_OBJ_PTR_EQ(o, handles.back().Get()); 94 EXPECT_TRUE(hs.Contains(handles.back().GetReference())); 95 EXPECT_TRUE(base->Contains(handles.back().GetReference())); 96 EXPECT_EQ(hs.NumberOfReferences(), base->NumberOfReferences()); 97 } 98 CollectVisitor visitor; 99 BaseHandleScope* base = &hs; 100 base->VisitRoots(visitor); 101 EXPECT_LE(visitor.visited.size(), base->NumberOfReferences()); 102 EXPECT_EQ(visitor.total_visited, base->NumberOfReferences()); 103 for (StackReference<mirror::Object>* ref : visitor.visited) { 104 EXPECT_TRUE(base->Contains(ref)); 105 } 106} 107 108} // namespace art 109