12c26501d24d929abe096ecce44f91410290b33c0Mathieu Chartier/* 22c26501d24d929abe096ecce44f91410290b33c0Mathieu Chartier * Copyright (C) 2014 The Android Open Source Project 32c26501d24d929abe096ecce44f91410290b33c0Mathieu Chartier * 42c26501d24d929abe096ecce44f91410290b33c0Mathieu Chartier * Licensed under the Apache License, Version 2.0 (the "License"); 52c26501d24d929abe096ecce44f91410290b33c0Mathieu Chartier * you may not use this file except in compliance with the License. 62c26501d24d929abe096ecce44f91410290b33c0Mathieu Chartier * You may obtain a copy of the License at 72c26501d24d929abe096ecce44f91410290b33c0Mathieu Chartier * 82c26501d24d929abe096ecce44f91410290b33c0Mathieu Chartier * http://www.apache.org/licenses/LICENSE-2.0 92c26501d24d929abe096ecce44f91410290b33c0Mathieu Chartier * 102c26501d24d929abe096ecce44f91410290b33c0Mathieu Chartier * Unless required by applicable law or agreed to in writing, software 112c26501d24d929abe096ecce44f91410290b33c0Mathieu Chartier * distributed under the License is distributed on an "AS IS" BASIS, 122c26501d24d929abe096ecce44f91410290b33c0Mathieu Chartier * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 132c26501d24d929abe096ecce44f91410290b33c0Mathieu Chartier * See the License for the specific language governing permissions and 142c26501d24d929abe096ecce44f91410290b33c0Mathieu Chartier * limitations under the License. 152c26501d24d929abe096ecce44f91410290b33c0Mathieu Chartier */ 162c26501d24d929abe096ecce44f91410290b33c0Mathieu Chartier 172c26501d24d929abe096ecce44f91410290b33c0Mathieu Chartier#include "card_table-inl.h" 182c26501d24d929abe096ecce44f91410290b33c0Mathieu Chartier 192c26501d24d929abe096ecce44f91410290b33c0Mathieu Chartier#include <string> 202c26501d24d929abe096ecce44f91410290b33c0Mathieu Chartier 212c26501d24d929abe096ecce44f91410290b33c0Mathieu Chartier#include "atomic.h" 222c26501d24d929abe096ecce44f91410290b33c0Mathieu Chartier#include "common_runtime_test.h" 232c26501d24d929abe096ecce44f91410290b33c0Mathieu Chartier#include "handle_scope-inl.h" 242c26501d24d929abe096ecce44f91410290b33c0Mathieu Chartier#include "mirror/class-inl.h" 252c26501d24d929abe096ecce44f91410290b33c0Mathieu Chartier#include "mirror/string-inl.h" // Strings are easiest to allocate 262c26501d24d929abe096ecce44f91410290b33c0Mathieu Chartier#include "scoped_thread_state_change.h" 272c26501d24d929abe096ecce44f91410290b33c0Mathieu Chartier#include "thread_pool.h" 282c26501d24d929abe096ecce44f91410290b33c0Mathieu Chartier#include "utils.h" 292c26501d24d929abe096ecce44f91410290b33c0Mathieu Chartier 302c26501d24d929abe096ecce44f91410290b33c0Mathieu Chartiernamespace art { 312c26501d24d929abe096ecce44f91410290b33c0Mathieu Chartier 322c26501d24d929abe096ecce44f91410290b33c0Mathieu Chartiernamespace mirror { 332c26501d24d929abe096ecce44f91410290b33c0Mathieu Chartier class Object; 342c26501d24d929abe096ecce44f91410290b33c0Mathieu Chartier} // namespace mirror 352c26501d24d929abe096ecce44f91410290b33c0Mathieu Chartier 3647e2e9592da2ebadd167ea8e588f95c179c47861Mathieu Chartiernamespace gc { 3747e2e9592da2ebadd167ea8e588f95c179c47861Mathieu Chartiernamespace accounting { 3847e2e9592da2ebadd167ea8e588f95c179c47861Mathieu Chartier 392c26501d24d929abe096ecce44f91410290b33c0Mathieu Chartierclass CardTableTest : public CommonRuntimeTest { 402c26501d24d929abe096ecce44f91410290b33c0Mathieu Chartier public: 4147e2e9592da2ebadd167ea8e588f95c179c47861Mathieu Chartier std::unique_ptr<CardTable> card_table_; 422c26501d24d929abe096ecce44f91410290b33c0Mathieu Chartier 432c26501d24d929abe096ecce44f91410290b33c0Mathieu Chartier void CommonSetup() { 442c26501d24d929abe096ecce44f91410290b33c0Mathieu Chartier if (card_table_.get() == nullptr) { 4547e2e9592da2ebadd167ea8e588f95c179c47861Mathieu Chartier card_table_.reset(CardTable::Create(heap_begin_, heap_size_)); 462c26501d24d929abe096ecce44f91410290b33c0Mathieu Chartier EXPECT_TRUE(card_table_.get() != nullptr); 472c26501d24d929abe096ecce44f91410290b33c0Mathieu Chartier } else { 482c26501d24d929abe096ecce44f91410290b33c0Mathieu Chartier ClearCardTable(); 492c26501d24d929abe096ecce44f91410290b33c0Mathieu Chartier } 502c26501d24d929abe096ecce44f91410290b33c0Mathieu Chartier } 512c26501d24d929abe096ecce44f91410290b33c0Mathieu Chartier // Default values for the test, not random to avoid undeterministic behaviour. 5213735955f39b3b304c37d2b2840663c131262c18Ian Rogers CardTableTest() : heap_begin_(reinterpret_cast<uint8_t*>(0x2000000)), heap_size_(2 * MB) { 532c26501d24d929abe096ecce44f91410290b33c0Mathieu Chartier } 542c26501d24d929abe096ecce44f91410290b33c0Mathieu Chartier void ClearCardTable() { 552c26501d24d929abe096ecce44f91410290b33c0Mathieu Chartier card_table_->ClearCardTable(); 562c26501d24d929abe096ecce44f91410290b33c0Mathieu Chartier } 5713735955f39b3b304c37d2b2840663c131262c18Ian Rogers uint8_t* HeapBegin() const { 582c26501d24d929abe096ecce44f91410290b33c0Mathieu Chartier return heap_begin_; 592c26501d24d929abe096ecce44f91410290b33c0Mathieu Chartier } 6013735955f39b3b304c37d2b2840663c131262c18Ian Rogers uint8_t* HeapLimit() const { 612c26501d24d929abe096ecce44f91410290b33c0Mathieu Chartier return HeapBegin() + heap_size_; 622c26501d24d929abe096ecce44f91410290b33c0Mathieu Chartier } 6347e2e9592da2ebadd167ea8e588f95c179c47861Mathieu Chartier // Return a pseudo random card for an address. 6413735955f39b3b304c37d2b2840663c131262c18Ian Rogers uint8_t PseudoRandomCard(const uint8_t* addr) const { 6547e2e9592da2ebadd167ea8e588f95c179c47861Mathieu Chartier size_t offset = RoundDown(addr - heap_begin_, CardTable::kCardSize); 662c26501d24d929abe096ecce44f91410290b33c0Mathieu Chartier return 1 + offset % 254; 672c26501d24d929abe096ecce44f91410290b33c0Mathieu Chartier } 682c26501d24d929abe096ecce44f91410290b33c0Mathieu Chartier void FillRandom() { 6913735955f39b3b304c37d2b2840663c131262c18Ian Rogers for (const uint8_t* addr = HeapBegin(); addr != HeapLimit(); addr += CardTable::kCardSize) { 702c26501d24d929abe096ecce44f91410290b33c0Mathieu Chartier EXPECT_TRUE(card_table_->AddrIsInCardTable(addr)); 7113735955f39b3b304c37d2b2840663c131262c18Ian Rogers uint8_t* card = card_table_->CardFromAddr(addr); 7247e2e9592da2ebadd167ea8e588f95c179c47861Mathieu Chartier *card = PseudoRandomCard(addr); 732c26501d24d929abe096ecce44f91410290b33c0Mathieu Chartier } 742c26501d24d929abe096ecce44f91410290b33c0Mathieu Chartier } 752c26501d24d929abe096ecce44f91410290b33c0Mathieu Chartier 762c26501d24d929abe096ecce44f91410290b33c0Mathieu Chartier private: 7713735955f39b3b304c37d2b2840663c131262c18Ian Rogers uint8_t* const heap_begin_; 782c26501d24d929abe096ecce44f91410290b33c0Mathieu Chartier const size_t heap_size_; 792c26501d24d929abe096ecce44f91410290b33c0Mathieu Chartier}; 802c26501d24d929abe096ecce44f91410290b33c0Mathieu Chartier 812c26501d24d929abe096ecce44f91410290b33c0Mathieu ChartierTEST_F(CardTableTest, TestMarkCard) { 822c26501d24d929abe096ecce44f91410290b33c0Mathieu Chartier CommonSetup(); 8313735955f39b3b304c37d2b2840663c131262c18Ian Rogers for (const uint8_t* addr = HeapBegin(); addr < HeapLimit(); addr += kObjectAlignment) { 842c26501d24d929abe096ecce44f91410290b33c0Mathieu Chartier auto obj = reinterpret_cast<const mirror::Object*>(addr); 8547e2e9592da2ebadd167ea8e588f95c179c47861Mathieu Chartier EXPECT_EQ(card_table_->GetCard(obj), CardTable::kCardClean); 862c26501d24d929abe096ecce44f91410290b33c0Mathieu Chartier EXPECT_TRUE(!card_table_->IsDirty(obj)); 872c26501d24d929abe096ecce44f91410290b33c0Mathieu Chartier card_table_->MarkCard(addr); 882c26501d24d929abe096ecce44f91410290b33c0Mathieu Chartier EXPECT_TRUE(card_table_->IsDirty(obj)); 8947e2e9592da2ebadd167ea8e588f95c179c47861Mathieu Chartier EXPECT_EQ(card_table_->GetCard(obj), CardTable::kCardDirty); 9013735955f39b3b304c37d2b2840663c131262c18Ian Rogers uint8_t* card_addr = card_table_->CardFromAddr(addr); 9147e2e9592da2ebadd167ea8e588f95c179c47861Mathieu Chartier EXPECT_EQ(*card_addr, CardTable::kCardDirty); 9247e2e9592da2ebadd167ea8e588f95c179c47861Mathieu Chartier *card_addr = CardTable::kCardClean; 9347e2e9592da2ebadd167ea8e588f95c179c47861Mathieu Chartier EXPECT_EQ(*card_addr, CardTable::kCardClean); 942c26501d24d929abe096ecce44f91410290b33c0Mathieu Chartier } 952c26501d24d929abe096ecce44f91410290b33c0Mathieu Chartier} 962c26501d24d929abe096ecce44f91410290b33c0Mathieu Chartier 972c26501d24d929abe096ecce44f91410290b33c0Mathieu Chartierclass UpdateVisitor { 982c26501d24d929abe096ecce44f91410290b33c0Mathieu Chartier public: 9913735955f39b3b304c37d2b2840663c131262c18Ian Rogers uint8_t operator()(uint8_t c) const { 1002c26501d24d929abe096ecce44f91410290b33c0Mathieu Chartier return c * 93 + 123; 1012c26501d24d929abe096ecce44f91410290b33c0Mathieu Chartier } 10213735955f39b3b304c37d2b2840663c131262c18Ian Rogers void operator()(uint8_t* /*card*/, uint8_t /*expected_value*/, uint8_t /*new_value*/) const { 1032c26501d24d929abe096ecce44f91410290b33c0Mathieu Chartier } 1042c26501d24d929abe096ecce44f91410290b33c0Mathieu Chartier}; 1052c26501d24d929abe096ecce44f91410290b33c0Mathieu Chartier 1062c26501d24d929abe096ecce44f91410290b33c0Mathieu ChartierTEST_F(CardTableTest, TestModifyCardsAtomic) { 1072c26501d24d929abe096ecce44f91410290b33c0Mathieu Chartier CommonSetup(); 1082c26501d24d929abe096ecce44f91410290b33c0Mathieu Chartier FillRandom(); 10947e2e9592da2ebadd167ea8e588f95c179c47861Mathieu Chartier const size_t delta = std::min(static_cast<size_t>(HeapLimit() - HeapBegin()), 11047e2e9592da2ebadd167ea8e588f95c179c47861Mathieu Chartier 8U * CardTable::kCardSize); 1112c26501d24d929abe096ecce44f91410290b33c0Mathieu Chartier UpdateVisitor visitor; 1122c26501d24d929abe096ecce44f91410290b33c0Mathieu Chartier size_t start_offset = 0; 11313735955f39b3b304c37d2b2840663c131262c18Ian Rogers for (uint8_t* cstart = HeapBegin(); cstart < HeapBegin() + delta; cstart += CardTable::kCardSize) { 11447e2e9592da2ebadd167ea8e588f95c179c47861Mathieu Chartier start_offset = (start_offset + kObjectAlignment) % CardTable::kCardSize; 1152c26501d24d929abe096ecce44f91410290b33c0Mathieu Chartier size_t end_offset = 0; 11613735955f39b3b304c37d2b2840663c131262c18Ian Rogers for (uint8_t* cend = HeapLimit() - delta; cend < HeapLimit(); cend += CardTable::kCardSize) { 1172c26501d24d929abe096ecce44f91410290b33c0Mathieu Chartier // Don't always start at a card boundary. 11813735955f39b3b304c37d2b2840663c131262c18Ian Rogers uint8_t* start = cstart + start_offset; 11913735955f39b3b304c37d2b2840663c131262c18Ian Rogers uint8_t* end = cend - end_offset; 12047e2e9592da2ebadd167ea8e588f95c179c47861Mathieu Chartier end_offset = (end_offset + kObjectAlignment) % CardTable::kCardSize; 1212c26501d24d929abe096ecce44f91410290b33c0Mathieu Chartier // Modify cards. 1222c26501d24d929abe096ecce44f91410290b33c0Mathieu Chartier card_table_->ModifyCardsAtomic(start, end, visitor, visitor); 1232c26501d24d929abe096ecce44f91410290b33c0Mathieu Chartier // Check adjacent cards not modified. 12413735955f39b3b304c37d2b2840663c131262c18Ian Rogers for (uint8_t* cur = start - CardTable::kCardSize; cur >= HeapBegin(); 12547e2e9592da2ebadd167ea8e588f95c179c47861Mathieu Chartier cur -= CardTable::kCardSize) { 12647e2e9592da2ebadd167ea8e588f95c179c47861Mathieu Chartier EXPECT_EQ(card_table_->GetCard(reinterpret_cast<mirror::Object*>(cur)), 12747e2e9592da2ebadd167ea8e588f95c179c47861Mathieu Chartier PseudoRandomCard(cur)); 1282c26501d24d929abe096ecce44f91410290b33c0Mathieu Chartier } 12913735955f39b3b304c37d2b2840663c131262c18Ian Rogers for (uint8_t* cur = end + CardTable::kCardSize; cur < HeapLimit(); 13047e2e9592da2ebadd167ea8e588f95c179c47861Mathieu Chartier cur += CardTable::kCardSize) { 13147e2e9592da2ebadd167ea8e588f95c179c47861Mathieu Chartier EXPECT_EQ(card_table_->GetCard(reinterpret_cast<mirror::Object*>(cur)), 13247e2e9592da2ebadd167ea8e588f95c179c47861Mathieu Chartier PseudoRandomCard(cur)); 1332c26501d24d929abe096ecce44f91410290b33c0Mathieu Chartier } 1342c26501d24d929abe096ecce44f91410290b33c0Mathieu Chartier // Verify Range. 13513735955f39b3b304c37d2b2840663c131262c18Ian Rogers for (uint8_t* cur = start; cur < AlignUp(end, CardTable::kCardSize); 13647e2e9592da2ebadd167ea8e588f95c179c47861Mathieu Chartier cur += CardTable::kCardSize) { 13713735955f39b3b304c37d2b2840663c131262c18Ian Rogers uint8_t* card = card_table_->CardFromAddr(cur); 13813735955f39b3b304c37d2b2840663c131262c18Ian Rogers uint8_t value = PseudoRandomCard(cur); 1392c26501d24d929abe096ecce44f91410290b33c0Mathieu Chartier EXPECT_EQ(visitor(value), *card); 1402c26501d24d929abe096ecce44f91410290b33c0Mathieu Chartier // Restore for next iteration. 1412c26501d24d929abe096ecce44f91410290b33c0Mathieu Chartier *card = value; 1422c26501d24d929abe096ecce44f91410290b33c0Mathieu Chartier } 1432c26501d24d929abe096ecce44f91410290b33c0Mathieu Chartier } 1442c26501d24d929abe096ecce44f91410290b33c0Mathieu Chartier } 1452c26501d24d929abe096ecce44f91410290b33c0Mathieu Chartier} 1462c26501d24d929abe096ecce44f91410290b33c0Mathieu Chartier 1472c26501d24d929abe096ecce44f91410290b33c0Mathieu Chartier// TODO: Add test for CardTable::Scan. 14847e2e9592da2ebadd167ea8e588f95c179c47861Mathieu Chartier} // namespace accounting 14947e2e9592da2ebadd167ea8e588f95c179c47861Mathieu Chartier} // namespace gc 1502c26501d24d929abe096ecce44f91410290b33c0Mathieu Chartier} // namespace art 151