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