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* link) : HandleScope(link, 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<0x9ABC> test_table(reinterpret_cast<HandleScope*>(0x5678)); 45 test_table.SetReference(0, reinterpret_cast<mirror::Object*>(0x1234)); 46 47 uint8_t* table_base_ptr = reinterpret_cast<uint8_t*>(&test_table); 48 49 { 50 uintptr_t* link_ptr = reinterpret_cast<uintptr_t*>(table_base_ptr + 51 HandleScope::LinkOffset(sizeof(void*))); 52 EXPECT_EQ(*link_ptr, static_cast<size_t>(0x5678)); 53 } 54 55 { 56 uint32_t* num_ptr = reinterpret_cast<uint32_t*>(table_base_ptr + 57 HandleScope::NumberOfReferencesOffset(sizeof(void*))); 58 EXPECT_EQ(*num_ptr, static_cast<size_t>(0x9ABC)); 59 } 60 61 { 62 // Assume sizeof(StackReference<mirror::Object>) == sizeof(uint32_t) 63 // TODO: How can we make this assumption-less but still access directly and fully? 64 EXPECT_EQ(sizeof(StackReference<mirror::Object>), sizeof(uint32_t)); 65 66 uint32_t* ref_ptr = reinterpret_cast<uint32_t*>(table_base_ptr + 67 HandleScope::ReferencesOffset(sizeof(void*))); 68 EXPECT_EQ(*ref_ptr, static_cast<uint32_t>(0x1234)); 69 } 70 } 71 72 } // namespace art 73