Home | History | Annotate | Download | only in runtime
      1 /*
      2  * Copyright (C) 2013 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 "mem_map.h"
     18 
     19 #include <memory>
     20 
     21 #include "common_runtime_test.h"
     22 #include "base/memory_tool.h"
     23 #include "base/unix_file/fd_file.h"
     24 
     25 namespace art {
     26 
     27 class MemMapTest : public CommonRuntimeTest {
     28  public:
     29   static uint8_t* BaseBegin(MemMap* mem_map) {
     30     return reinterpret_cast<uint8_t*>(mem_map->base_begin_);
     31   }
     32 
     33   static size_t BaseSize(MemMap* mem_map) {
     34     return mem_map->base_size_;
     35   }
     36 
     37   static uint8_t* GetValidMapAddress(size_t size, bool low_4gb) {
     38     // Find a valid map address and unmap it before returning.
     39     std::string error_msg;
     40     std::unique_ptr<MemMap> map(MemMap::MapAnonymous("temp",
     41                                                      nullptr,
     42                                                      size,
     43                                                      PROT_READ,
     44                                                      low_4gb,
     45                                                      false,
     46                                                      &error_msg));
     47     CHECK(map != nullptr);
     48     return map->Begin();
     49   }
     50 
     51   static void RemapAtEndTest(bool low_4gb) {
     52     std::string error_msg;
     53     // Cast the page size to size_t.
     54     const size_t page_size = static_cast<size_t>(kPageSize);
     55     // Map a two-page memory region.
     56     MemMap* m0 = MemMap::MapAnonymous("MemMapTest_RemapAtEndTest_map0",
     57                                       nullptr,
     58                                       2 * page_size,
     59                                       PROT_READ | PROT_WRITE,
     60                                       low_4gb,
     61                                       false,
     62                                       &error_msg);
     63     // Check its state and write to it.
     64     uint8_t* base0 = m0->Begin();
     65     ASSERT_TRUE(base0 != nullptr) << error_msg;
     66     size_t size0 = m0->Size();
     67     EXPECT_EQ(m0->Size(), 2 * page_size);
     68     EXPECT_EQ(BaseBegin(m0), base0);
     69     EXPECT_EQ(BaseSize(m0), size0);
     70     memset(base0, 42, 2 * page_size);
     71     // Remap the latter half into a second MemMap.
     72     MemMap* m1 = m0->RemapAtEnd(base0 + page_size,
     73                                 "MemMapTest_RemapAtEndTest_map1",
     74                                 PROT_READ | PROT_WRITE,
     75                                 &error_msg);
     76     // Check the states of the two maps.
     77     EXPECT_EQ(m0->Begin(), base0) << error_msg;
     78     EXPECT_EQ(m0->Size(), page_size);
     79     EXPECT_EQ(BaseBegin(m0), base0);
     80     EXPECT_EQ(BaseSize(m0), page_size);
     81     uint8_t* base1 = m1->Begin();
     82     size_t size1 = m1->Size();
     83     EXPECT_EQ(base1, base0 + page_size);
     84     EXPECT_EQ(size1, page_size);
     85     EXPECT_EQ(BaseBegin(m1), base1);
     86     EXPECT_EQ(BaseSize(m1), size1);
     87     // Write to the second region.
     88     memset(base1, 43, page_size);
     89     // Check the contents of the two regions.
     90     for (size_t i = 0; i < page_size; ++i) {
     91       EXPECT_EQ(base0[i], 42);
     92     }
     93     for (size_t i = 0; i < page_size; ++i) {
     94       EXPECT_EQ(base1[i], 43);
     95     }
     96     // Unmap the first region.
     97     delete m0;
     98     // Make sure the second region is still accessible after the first
     99     // region is unmapped.
    100     for (size_t i = 0; i < page_size; ++i) {
    101       EXPECT_EQ(base1[i], 43);
    102     }
    103     delete m1;
    104   }
    105 
    106   void CommonInit() {
    107     MemMap::Init();
    108   }
    109 
    110 #if defined(__LP64__) && !defined(__x86_64__)
    111   static uintptr_t GetLinearScanPos() {
    112     return MemMap::next_mem_pos_;
    113   }
    114 #endif
    115 };
    116 
    117 #if defined(__LP64__) && !defined(__x86_64__)
    118 
    119 #ifdef __BIONIC__
    120 extern uintptr_t CreateStartPos(uint64_t input);
    121 #endif
    122 
    123 TEST_F(MemMapTest, Start) {
    124   CommonInit();
    125   uintptr_t start = GetLinearScanPos();
    126   EXPECT_LE(64 * KB, start);
    127   EXPECT_LT(start, static_cast<uintptr_t>(ART_BASE_ADDRESS));
    128 #ifdef __BIONIC__
    129   // Test a couple of values. Make sure they are different.
    130   uintptr_t last = 0;
    131   for (size_t i = 0; i < 100; ++i) {
    132     uintptr_t random_start = CreateStartPos(i * kPageSize);
    133     EXPECT_NE(last, random_start);
    134     last = random_start;
    135   }
    136 
    137   // Even on max, should be below ART_BASE_ADDRESS.
    138   EXPECT_LT(CreateStartPos(~0), static_cast<uintptr_t>(ART_BASE_ADDRESS));
    139 #endif
    140   // End of test.
    141 }
    142 #endif
    143 
    144 TEST_F(MemMapTest, MapAnonymousEmpty) {
    145   CommonInit();
    146   std::string error_msg;
    147   std::unique_ptr<MemMap> map(MemMap::MapAnonymous("MapAnonymousEmpty",
    148                                                    nullptr,
    149                                                    0,
    150                                                    PROT_READ,
    151                                                    false,
    152                                                    false,
    153                                                    &error_msg));
    154   ASSERT_TRUE(map.get() != nullptr) << error_msg;
    155   ASSERT_TRUE(error_msg.empty());
    156   map.reset(MemMap::MapAnonymous("MapAnonymousEmpty",
    157                                  nullptr,
    158                                  kPageSize,
    159                                  PROT_READ | PROT_WRITE,
    160                                  false,
    161                                  false,
    162                                  &error_msg));
    163   ASSERT_TRUE(map.get() != nullptr) << error_msg;
    164   ASSERT_TRUE(error_msg.empty());
    165 }
    166 
    167 TEST_F(MemMapTest, MapAnonymousFailNullError) {
    168   CommonInit();
    169   // Test that we don't crash with a null error_str when mapping at an invalid location.
    170   std::unique_ptr<MemMap> map(MemMap::MapAnonymous("MapAnonymousInvalid",
    171                                                     reinterpret_cast<uint8_t*>(kPageSize),
    172                                                     0x20000,
    173                                                     PROT_READ | PROT_WRITE,
    174                                                     false,
    175                                                     false,
    176                                                     nullptr));
    177   ASSERT_EQ(nullptr, map.get());
    178 }
    179 
    180 #ifdef __LP64__
    181 TEST_F(MemMapTest, MapAnonymousEmpty32bit) {
    182   CommonInit();
    183   std::string error_msg;
    184   std::unique_ptr<MemMap> map(MemMap::MapAnonymous("MapAnonymousEmpty",
    185                                                    nullptr,
    186                                                    kPageSize,
    187                                                    PROT_READ | PROT_WRITE,
    188                                                    true,
    189                                                    false,
    190                                                    &error_msg));
    191   ASSERT_TRUE(map.get() != nullptr) << error_msg;
    192   ASSERT_TRUE(error_msg.empty());
    193   ASSERT_LT(reinterpret_cast<uintptr_t>(BaseBegin(map.get())), 1ULL << 32);
    194 }
    195 TEST_F(MemMapTest, MapFile32Bit) {
    196   CommonInit();
    197   std::string error_msg;
    198   ScratchFile scratch_file;
    199   constexpr size_t kMapSize = kPageSize;
    200   std::unique_ptr<uint8_t[]> data(new uint8_t[kMapSize]());
    201   ASSERT_TRUE(scratch_file.GetFile()->WriteFully(&data[0], kMapSize));
    202   std::unique_ptr<MemMap> map(MemMap::MapFile(/*byte_count*/kMapSize,
    203                                               PROT_READ,
    204                                               MAP_PRIVATE,
    205                                               scratch_file.GetFd(),
    206                                               /*start*/0,
    207                                               /*low_4gb*/true,
    208                                               scratch_file.GetFilename().c_str(),
    209                                               &error_msg));
    210   ASSERT_TRUE(map != nullptr) << error_msg;
    211   ASSERT_TRUE(error_msg.empty());
    212   ASSERT_EQ(map->Size(), kMapSize);
    213   ASSERT_LT(reinterpret_cast<uintptr_t>(BaseBegin(map.get())), 1ULL << 32);
    214 }
    215 #endif
    216 
    217 TEST_F(MemMapTest, MapAnonymousExactAddr) {
    218   CommonInit();
    219   std::string error_msg;
    220   // Find a valid address.
    221   uint8_t* valid_address = GetValidMapAddress(kPageSize, /*low_4gb*/false);
    222   // Map at an address that should work, which should succeed.
    223   std::unique_ptr<MemMap> map0(MemMap::MapAnonymous("MapAnonymous0",
    224                                                     valid_address,
    225                                                     kPageSize,
    226                                                     PROT_READ | PROT_WRITE,
    227                                                     false,
    228                                                     false,
    229                                                     &error_msg));
    230   ASSERT_TRUE(map0.get() != nullptr) << error_msg;
    231   ASSERT_TRUE(error_msg.empty());
    232   ASSERT_TRUE(map0->BaseBegin() == valid_address);
    233   // Map at an unspecified address, which should succeed.
    234   std::unique_ptr<MemMap> map1(MemMap::MapAnonymous("MapAnonymous1",
    235                                                     nullptr,
    236                                                     kPageSize,
    237                                                     PROT_READ | PROT_WRITE,
    238                                                     false,
    239                                                     false,
    240                                                     &error_msg));
    241   ASSERT_TRUE(map1.get() != nullptr) << error_msg;
    242   ASSERT_TRUE(error_msg.empty());
    243   ASSERT_TRUE(map1->BaseBegin() != nullptr);
    244   // Attempt to map at the same address, which should fail.
    245   std::unique_ptr<MemMap> map2(MemMap::MapAnonymous("MapAnonymous2",
    246                                                     reinterpret_cast<uint8_t*>(map1->BaseBegin()),
    247                                                     kPageSize,
    248                                                     PROT_READ | PROT_WRITE,
    249                                                     false,
    250                                                     false,
    251                                                     &error_msg));
    252   ASSERT_TRUE(map2.get() == nullptr) << error_msg;
    253   ASSERT_TRUE(!error_msg.empty());
    254 }
    255 
    256 TEST_F(MemMapTest, RemapAtEnd) {
    257   RemapAtEndTest(false);
    258 }
    259 
    260 #ifdef __LP64__
    261 TEST_F(MemMapTest, RemapAtEnd32bit) {
    262   RemapAtEndTest(true);
    263 }
    264 #endif
    265 
    266 TEST_F(MemMapTest, MapAnonymousExactAddr32bitHighAddr) {
    267   // Some MIPS32 hardware (namely the Creator Ci20 development board)
    268   // cannot allocate in the 2GB-4GB region.
    269   TEST_DISABLED_FOR_MIPS();
    270 
    271   CommonInit();
    272   // This test may not work under valgrind.
    273   if (RUNNING_ON_MEMORY_TOOL == 0) {
    274     constexpr size_t size = 0x100000;
    275     // Try all addresses starting from 2GB to 4GB.
    276     size_t start_addr = 2 * GB;
    277     std::string error_msg;
    278     std::unique_ptr<MemMap> map;
    279     for (; start_addr <= std::numeric_limits<uint32_t>::max() - size; start_addr += size) {
    280       map.reset(MemMap::MapAnonymous("MapAnonymousExactAddr32bitHighAddr",
    281                                      reinterpret_cast<uint8_t*>(start_addr),
    282                                      size,
    283                                      PROT_READ | PROT_WRITE,
    284                                      /*low_4gb*/true,
    285                                      false,
    286                                      &error_msg));
    287       if (map != nullptr) {
    288         break;
    289       }
    290     }
    291     ASSERT_TRUE(map.get() != nullptr) << error_msg;
    292     ASSERT_GE(reinterpret_cast<uintptr_t>(map->End()), 2u * GB);
    293     ASSERT_TRUE(error_msg.empty());
    294     ASSERT_EQ(BaseBegin(map.get()), reinterpret_cast<void*>(start_addr));
    295   }
    296 }
    297 
    298 TEST_F(MemMapTest, MapAnonymousOverflow) {
    299   CommonInit();
    300   std::string error_msg;
    301   uintptr_t ptr = 0;
    302   ptr -= kPageSize;  // Now it's close to the top.
    303   std::unique_ptr<MemMap> map(MemMap::MapAnonymous("MapAnonymousOverflow",
    304                                                    reinterpret_cast<uint8_t*>(ptr),
    305                                                    2 * kPageSize,  // brings it over the top.
    306                                                    PROT_READ | PROT_WRITE,
    307                                                    false,
    308                                                    false,
    309                                                    &error_msg));
    310   ASSERT_EQ(nullptr, map.get());
    311   ASSERT_FALSE(error_msg.empty());
    312 }
    313 
    314 #ifdef __LP64__
    315 TEST_F(MemMapTest, MapAnonymousLow4GBExpectedTooHigh) {
    316   CommonInit();
    317   std::string error_msg;
    318   std::unique_ptr<MemMap> map(
    319       MemMap::MapAnonymous("MapAnonymousLow4GBExpectedTooHigh",
    320                            reinterpret_cast<uint8_t*>(UINT64_C(0x100000000)),
    321                            kPageSize,
    322                            PROT_READ | PROT_WRITE,
    323                            true,
    324                            false,
    325                            &error_msg));
    326   ASSERT_EQ(nullptr, map.get());
    327   ASSERT_FALSE(error_msg.empty());
    328 }
    329 
    330 TEST_F(MemMapTest, MapAnonymousLow4GBRangeTooHigh) {
    331   CommonInit();
    332   std::string error_msg;
    333   std::unique_ptr<MemMap> map(MemMap::MapAnonymous("MapAnonymousLow4GBRangeTooHigh",
    334                                                    reinterpret_cast<uint8_t*>(0xF0000000),
    335                                                    0x20000000,
    336                                                    PROT_READ | PROT_WRITE,
    337                                                    true,
    338                                                    false,
    339                                                    &error_msg));
    340   ASSERT_EQ(nullptr, map.get());
    341   ASSERT_FALSE(error_msg.empty());
    342 }
    343 #endif
    344 
    345 TEST_F(MemMapTest, MapAnonymousReuse) {
    346   CommonInit();
    347   std::string error_msg;
    348   std::unique_ptr<MemMap> map(MemMap::MapAnonymous("MapAnonymousReserve",
    349                                                    nullptr,
    350                                                    0x20000,
    351                                                    PROT_READ | PROT_WRITE,
    352                                                    false,
    353                                                    false,
    354                                                    &error_msg));
    355   ASSERT_NE(nullptr, map.get());
    356   ASSERT_TRUE(error_msg.empty());
    357   std::unique_ptr<MemMap> map2(MemMap::MapAnonymous("MapAnonymousReused",
    358                                                     reinterpret_cast<uint8_t*>(map->BaseBegin()),
    359                                                     0x10000,
    360                                                     PROT_READ | PROT_WRITE,
    361                                                     false,
    362                                                     true,
    363                                                     &error_msg));
    364   ASSERT_NE(nullptr, map2.get());
    365   ASSERT_TRUE(error_msg.empty());
    366 }
    367 
    368 TEST_F(MemMapTest, CheckNoGaps) {
    369   CommonInit();
    370   std::string error_msg;
    371   constexpr size_t kNumPages = 3;
    372   // Map a 3-page mem map.
    373   std::unique_ptr<MemMap> map(MemMap::MapAnonymous("MapAnonymous0",
    374                                                    nullptr,
    375                                                    kPageSize * kNumPages,
    376                                                    PROT_READ | PROT_WRITE,
    377                                                    false,
    378                                                    false,
    379                                                    &error_msg));
    380   ASSERT_TRUE(map.get() != nullptr) << error_msg;
    381   ASSERT_TRUE(error_msg.empty());
    382   // Record the base address.
    383   uint8_t* map_base = reinterpret_cast<uint8_t*>(map->BaseBegin());
    384   // Unmap it.
    385   map.reset();
    386 
    387   // Map at the same address, but in page-sized separate mem maps,
    388   // assuming the space at the address is still available.
    389   std::unique_ptr<MemMap> map0(MemMap::MapAnonymous("MapAnonymous0",
    390                                                     map_base,
    391                                                     kPageSize,
    392                                                     PROT_READ | PROT_WRITE,
    393                                                     false,
    394                                                     false,
    395                                                     &error_msg));
    396   ASSERT_TRUE(map0.get() != nullptr) << error_msg;
    397   ASSERT_TRUE(error_msg.empty());
    398   std::unique_ptr<MemMap> map1(MemMap::MapAnonymous("MapAnonymous1",
    399                                                     map_base + kPageSize,
    400                                                     kPageSize,
    401                                                     PROT_READ | PROT_WRITE,
    402                                                     false,
    403                                                     false,
    404                                                     &error_msg));
    405   ASSERT_TRUE(map1.get() != nullptr) << error_msg;
    406   ASSERT_TRUE(error_msg.empty());
    407   std::unique_ptr<MemMap> map2(MemMap::MapAnonymous("MapAnonymous2",
    408                                                     map_base + kPageSize * 2,
    409                                                     kPageSize,
    410                                                     PROT_READ | PROT_WRITE,
    411                                                     false,
    412                                                     false,
    413                                                     &error_msg));
    414   ASSERT_TRUE(map2.get() != nullptr) << error_msg;
    415   ASSERT_TRUE(error_msg.empty());
    416 
    417   // One-map cases.
    418   ASSERT_TRUE(MemMap::CheckNoGaps(map0.get(), map0.get()));
    419   ASSERT_TRUE(MemMap::CheckNoGaps(map1.get(), map1.get()));
    420   ASSERT_TRUE(MemMap::CheckNoGaps(map2.get(), map2.get()));
    421 
    422   // Two or three-map cases.
    423   ASSERT_TRUE(MemMap::CheckNoGaps(map0.get(), map1.get()));
    424   ASSERT_TRUE(MemMap::CheckNoGaps(map1.get(), map2.get()));
    425   ASSERT_TRUE(MemMap::CheckNoGaps(map0.get(), map2.get()));
    426 
    427   // Unmap the middle one.
    428   map1.reset();
    429 
    430   // Should return false now that there's a gap in the middle.
    431   ASSERT_FALSE(MemMap::CheckNoGaps(map0.get(), map2.get()));
    432 }
    433 
    434 TEST_F(MemMapTest, AlignBy) {
    435   CommonInit();
    436   std::string error_msg;
    437   // Cast the page size to size_t.
    438   const size_t page_size = static_cast<size_t>(kPageSize);
    439   // Map a region.
    440   std::unique_ptr<MemMap> m0(MemMap::MapAnonymous("MemMapTest_AlignByTest_map0",
    441                                                   nullptr,
    442                                                   14 * page_size,
    443                                                   PROT_READ | PROT_WRITE,
    444                                                   false,
    445                                                   false,
    446                                                   &error_msg));
    447   uint8_t* base0 = m0->Begin();
    448   ASSERT_TRUE(base0 != nullptr) << error_msg;
    449   ASSERT_EQ(m0->Size(), 14 * page_size);
    450   ASSERT_EQ(BaseBegin(m0.get()), base0);
    451   ASSERT_EQ(BaseSize(m0.get()), m0->Size());
    452 
    453   // Break it into several regions by using RemapAtEnd.
    454   std::unique_ptr<MemMap> m1(m0->RemapAtEnd(base0 + 3 * page_size,
    455                                             "MemMapTest_AlignByTest_map1",
    456                                             PROT_READ | PROT_WRITE,
    457                                             &error_msg));
    458   uint8_t* base1 = m1->Begin();
    459   ASSERT_TRUE(base1 != nullptr) << error_msg;
    460   ASSERT_EQ(base1, base0 + 3 * page_size);
    461   ASSERT_EQ(m0->Size(), 3 * page_size);
    462 
    463   std::unique_ptr<MemMap> m2(m1->RemapAtEnd(base1 + 4 * page_size,
    464                                             "MemMapTest_AlignByTest_map2",
    465                                             PROT_READ | PROT_WRITE,
    466                                             &error_msg));
    467   uint8_t* base2 = m2->Begin();
    468   ASSERT_TRUE(base2 != nullptr) << error_msg;
    469   ASSERT_EQ(base2, base1 + 4 * page_size);
    470   ASSERT_EQ(m1->Size(), 4 * page_size);
    471 
    472   std::unique_ptr<MemMap> m3(m2->RemapAtEnd(base2 + 3 * page_size,
    473                                             "MemMapTest_AlignByTest_map1",
    474                                             PROT_READ | PROT_WRITE,
    475                                             &error_msg));
    476   uint8_t* base3 = m3->Begin();
    477   ASSERT_TRUE(base3 != nullptr) << error_msg;
    478   ASSERT_EQ(base3, base2 + 3 * page_size);
    479   ASSERT_EQ(m2->Size(), 3 * page_size);
    480   ASSERT_EQ(m3->Size(), 4 * page_size);
    481 
    482   uint8_t* end0 = base0 + m0->Size();
    483   uint8_t* end1 = base1 + m1->Size();
    484   uint8_t* end2 = base2 + m2->Size();
    485   uint8_t* end3 = base3 + m3->Size();
    486 
    487   ASSERT_EQ(static_cast<size_t>(end3 - base0), 14 * page_size);
    488 
    489   if (IsAlignedParam(base0, 2 * page_size)) {
    490     ASSERT_FALSE(IsAlignedParam(base1, 2 * page_size));
    491     ASSERT_FALSE(IsAlignedParam(base2, 2 * page_size));
    492     ASSERT_TRUE(IsAlignedParam(base3, 2 * page_size));
    493     ASSERT_TRUE(IsAlignedParam(end3, 2 * page_size));
    494   } else {
    495     ASSERT_TRUE(IsAlignedParam(base1, 2 * page_size));
    496     ASSERT_TRUE(IsAlignedParam(base2, 2 * page_size));
    497     ASSERT_FALSE(IsAlignedParam(base3, 2 * page_size));
    498     ASSERT_FALSE(IsAlignedParam(end3, 2 * page_size));
    499   }
    500 
    501   // Align by 2 * page_size;
    502   m0->AlignBy(2 * page_size);
    503   m1->AlignBy(2 * page_size);
    504   m2->AlignBy(2 * page_size);
    505   m3->AlignBy(2 * page_size);
    506 
    507   EXPECT_TRUE(IsAlignedParam(m0->Begin(), 2 * page_size));
    508   EXPECT_TRUE(IsAlignedParam(m1->Begin(), 2 * page_size));
    509   EXPECT_TRUE(IsAlignedParam(m2->Begin(), 2 * page_size));
    510   EXPECT_TRUE(IsAlignedParam(m3->Begin(), 2 * page_size));
    511 
    512   EXPECT_TRUE(IsAlignedParam(m0->Begin() + m0->Size(), 2 * page_size));
    513   EXPECT_TRUE(IsAlignedParam(m1->Begin() + m1->Size(), 2 * page_size));
    514   EXPECT_TRUE(IsAlignedParam(m2->Begin() + m2->Size(), 2 * page_size));
    515   EXPECT_TRUE(IsAlignedParam(m3->Begin() + m3->Size(), 2 * page_size));
    516 
    517   if (IsAlignedParam(base0, 2 * page_size)) {
    518     EXPECT_EQ(m0->Begin(), base0);
    519     EXPECT_EQ(m0->Begin() + m0->Size(), end0 - page_size);
    520     EXPECT_EQ(m1->Begin(), base1 + page_size);
    521     EXPECT_EQ(m1->Begin() + m1->Size(), end1 - page_size);
    522     EXPECT_EQ(m2->Begin(), base2 + page_size);
    523     EXPECT_EQ(m2->Begin() + m2->Size(), end2);
    524     EXPECT_EQ(m3->Begin(), base3);
    525     EXPECT_EQ(m3->Begin() + m3->Size(), end3);
    526   } else {
    527     EXPECT_EQ(m0->Begin(), base0 + page_size);
    528     EXPECT_EQ(m0->Begin() + m0->Size(), end0);
    529     EXPECT_EQ(m1->Begin(), base1);
    530     EXPECT_EQ(m1->Begin() + m1->Size(), end1);
    531     EXPECT_EQ(m2->Begin(), base2);
    532     EXPECT_EQ(m2->Begin() + m2->Size(), end2 - page_size);
    533     EXPECT_EQ(m3->Begin(), base3 + page_size);
    534     EXPECT_EQ(m3->Begin() + m3->Size(), end3 - page_size);
    535   }
    536 }
    537 
    538 }  // namespace art
    539