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