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 "gtest/gtest.h" 18 #include "handle_scope-inl.h" 19 #include "scoped_thread_state_change.h" 20 #include "thread.h" 21 22 namespace art { 23 24 // Handle scope with a fixed size which is allocated on the stack. 25 template<size_t kNumReferences> 26 class NoThreadStackHandleScope : public HandleScope { 27 public: 28 explicit NoThreadStackHandleScope() : HandleScope(kNumReferences) { 29 } 30 ~NoThreadStackHandleScope() { 31 } 32 33 private: 34 // references_storage_ needs to be first so that it matches the address of references_ 35 StackReference<mirror::Object> references_storage_[kNumReferences]; 36 }; 37 38 // Test the offsets computed for members of HandleScope. Because of cross-compiling 39 // it is impossible the use OFFSETOF_MEMBER, so we do some reasonable computations ourselves. This 40 // test checks whether we do the right thing. 41 TEST(HandleScopeTest, Offsets) NO_THREAD_SAFETY_ANALYSIS { 42 // As the members of HandleScope are private, we cannot use OFFSETOF_MEMBER 43 // here. So do the inverse: set some data, and access it through pointers created from the offsets. 44 NoThreadStackHandleScope<1> test_table; 45 test_table.SetReference(0, reinterpret_cast<mirror::Object*>(0x1234)); 46 test_table.SetLink(reinterpret_cast<HandleScope*>(0x5678)); 47 test_table.SetNumberOfReferences(0x9ABC); 48 49 byte* table_base_ptr = reinterpret_cast<byte*>(&test_table); 50 51 { 52 uintptr_t* link_ptr = reinterpret_cast<uintptr_t*>(table_base_ptr + 53 HandleScope::LinkOffset(kPointerSize)); 54 EXPECT_EQ(*link_ptr, static_cast<size_t>(0x5678)); 55 } 56 57 { 58 uint32_t* num_ptr = reinterpret_cast<uint32_t*>(table_base_ptr + 59 HandleScope::NumberOfReferencesOffset(kPointerSize)); 60 EXPECT_EQ(*num_ptr, static_cast<size_t>(0x9ABC)); 61 } 62 63 { 64 // Assume sizeof(StackReference<mirror::Object>) == sizeof(uint32_t) 65 // TODO: How can we make this assumption-less but still access directly and fully? 66 EXPECT_EQ(sizeof(StackReference<mirror::Object>), sizeof(uint32_t)); 67 68 uint32_t* ref_ptr = reinterpret_cast<uint32_t*>(table_base_ptr + 69 HandleScope::ReferencesOffset(kPointerSize)); 70 EXPECT_EQ(*ref_ptr, static_cast<uint32_t>(0x1234)); 71 } 72 } 73 74 } // namespace art 75