1a7433515114ae725c3427cd510f76b84107170a1Andreas Gampe/*
2a7433515114ae725c3427cd510f76b84107170a1Andreas Gampe * Copyright (C) 2011 The Android Open Source Project
3a7433515114ae725c3427cd510f76b84107170a1Andreas Gampe *
4a7433515114ae725c3427cd510f76b84107170a1Andreas Gampe * Licensed under the Apache License, Version 2.0 (the "License");
5a7433515114ae725c3427cd510f76b84107170a1Andreas Gampe * you may not use this file except in compliance with the License.
6a7433515114ae725c3427cd510f76b84107170a1Andreas Gampe * You may obtain a copy of the License at
7a7433515114ae725c3427cd510f76b84107170a1Andreas Gampe *
8a7433515114ae725c3427cd510f76b84107170a1Andreas Gampe *      http://www.apache.org/licenses/LICENSE-2.0
9a7433515114ae725c3427cd510f76b84107170a1Andreas Gampe *
10a7433515114ae725c3427cd510f76b84107170a1Andreas Gampe * Unless required by applicable law or agreed to in writing, software
11a7433515114ae725c3427cd510f76b84107170a1Andreas Gampe * distributed under the License is distributed on an "AS IS" BASIS,
12a7433515114ae725c3427cd510f76b84107170a1Andreas Gampe * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13a7433515114ae725c3427cd510f76b84107170a1Andreas Gampe * See the License for the specific language governing permissions and
14a7433515114ae725c3427cd510f76b84107170a1Andreas Gampe * limitations under the License.
15a7433515114ae725c3427cd510f76b84107170a1Andreas Gampe */
16a7433515114ae725c3427cd510f76b84107170a1Andreas Gampe
1741b175aba41c9365a1c53b8a1afbd17129c87c14Vladimir Marko#include "base/time_utils.h"
18a7433515114ae725c3427cd510f76b84107170a1Andreas Gampe#include "space_test.h"
19a7433515114ae725c3427cd510f76b84107170a1Andreas Gampe#include "large_object_space.h"
20a7433515114ae725c3427cd510f76b84107170a1Andreas Gampe
21a7433515114ae725c3427cd510f76b84107170a1Andreas Gampenamespace art {
22a7433515114ae725c3427cd510f76b84107170a1Andreas Gampenamespace gc {
23a7433515114ae725c3427cd510f76b84107170a1Andreas Gampenamespace space {
24a7433515114ae725c3427cd510f76b84107170a1Andreas Gampe
25a7433515114ae725c3427cd510f76b84107170a1Andreas Gampeclass LargeObjectSpaceTest : public SpaceTest {
26a7433515114ae725c3427cd510f76b84107170a1Andreas Gampe public:
27a7433515114ae725c3427cd510f76b84107170a1Andreas Gampe  void LargeObjectTest();
28b870823dd181571e10ecda58a6b5660e62bb18beAndreas Gampe
29b870823dd181571e10ecda58a6b5660e62bb18beAndreas Gampe  static constexpr size_t kNumThreads = 10;
30b870823dd181571e10ecda58a6b5660e62bb18beAndreas Gampe  static constexpr size_t kNumIterations = 1000;
31b870823dd181571e10ecda58a6b5660e62bb18beAndreas Gampe  void RaceTest();
32a7433515114ae725c3427cd510f76b84107170a1Andreas Gampe};
33a7433515114ae725c3427cd510f76b84107170a1Andreas Gampe
34a7433515114ae725c3427cd510f76b84107170a1Andreas Gampe
35a7433515114ae725c3427cd510f76b84107170a1Andreas Gampevoid LargeObjectSpaceTest::LargeObjectTest() {
36a7433515114ae725c3427cd510f76b84107170a1Andreas Gampe  size_t rand_seed = 0;
378f23620d45399286564986d2541cda761b3fe0acMathieu Chartier  Thread* const self = Thread::Current();
38a7433515114ae725c3427cd510f76b84107170a1Andreas Gampe  for (size_t i = 0; i < 2; ++i) {
39a7433515114ae725c3427cd510f76b84107170a1Andreas Gampe    LargeObjectSpace* los = nullptr;
40a7433515114ae725c3427cd510f76b84107170a1Andreas Gampe    if (i == 0) {
41a7433515114ae725c3427cd510f76b84107170a1Andreas Gampe      los = space::LargeObjectMapSpace::Create("large object space");
42a7433515114ae725c3427cd510f76b84107170a1Andreas Gampe    } else {
43a7433515114ae725c3427cd510f76b84107170a1Andreas Gampe      los = space::FreeListSpace::Create("large object space", nullptr, 128 * MB);
44a7433515114ae725c3427cd510f76b84107170a1Andreas Gampe    }
45a7433515114ae725c3427cd510f76b84107170a1Andreas Gampe
46a7433515114ae725c3427cd510f76b84107170a1Andreas Gampe    static const size_t num_allocations = 64;
47a7433515114ae725c3427cd510f76b84107170a1Andreas Gampe    static const size_t max_allocation_size = 0x100000;
48700a402244a1a423da4f3ba8032459f4b65fa18fIan Rogers    std::vector<std::pair<mirror::Object*, size_t>> requests;
49a7433515114ae725c3427cd510f76b84107170a1Andreas Gampe
50a7433515114ae725c3427cd510f76b84107170a1Andreas Gampe    for (size_t phase = 0; phase < 2; ++phase) {
51a7433515114ae725c3427cd510f76b84107170a1Andreas Gampe      while (requests.size() < num_allocations) {
52a7433515114ae725c3427cd510f76b84107170a1Andreas Gampe        size_t request_size = test_rand(&rand_seed) % max_allocation_size;
53a7433515114ae725c3427cd510f76b84107170a1Andreas Gampe        size_t allocation_size = 0;
544460a84be92b5a94ecfb5c650aef4945ab849c93Hiroshi Yamauchi        size_t bytes_tl_bulk_allocated;
558f23620d45399286564986d2541cda761b3fe0acMathieu Chartier        mirror::Object* obj = los->Alloc(self, request_size, &allocation_size, nullptr,
568f23620d45399286564986d2541cda761b3fe0acMathieu Chartier                                         &bytes_tl_bulk_allocated);
57a7433515114ae725c3427cd510f76b84107170a1Andreas Gampe        ASSERT_TRUE(obj != nullptr);
586fac447555dc94a935b78198479cce645c837b89Ian Rogers        ASSERT_EQ(allocation_size, los->AllocationSize(obj, nullptr));
59a7433515114ae725c3427cd510f76b84107170a1Andreas Gampe        ASSERT_GE(allocation_size, request_size);
604460a84be92b5a94ecfb5c650aef4945ab849c93Hiroshi Yamauchi        ASSERT_EQ(allocation_size, bytes_tl_bulk_allocated);
61a7433515114ae725c3427cd510f76b84107170a1Andreas Gampe        // Fill in our magic value.
6213735955f39b3b304c37d2b2840663c131262c18Ian Rogers        uint8_t magic = (request_size & 0xFF) | 1;
63a7433515114ae725c3427cd510f76b84107170a1Andreas Gampe        memset(obj, magic, request_size);
64a7433515114ae725c3427cd510f76b84107170a1Andreas Gampe        requests.push_back(std::make_pair(obj, request_size));
65a7433515114ae725c3427cd510f76b84107170a1Andreas Gampe      }
66a7433515114ae725c3427cd510f76b84107170a1Andreas Gampe
67a7433515114ae725c3427cd510f76b84107170a1Andreas Gampe      // "Randomly" shuffle the requests.
68a7433515114ae725c3427cd510f76b84107170a1Andreas Gampe      for (size_t k = 0; k < 10; ++k) {
69a7433515114ae725c3427cd510f76b84107170a1Andreas Gampe        for (size_t j = 0; j < requests.size(); ++j) {
70a7433515114ae725c3427cd510f76b84107170a1Andreas Gampe          std::swap(requests[j], requests[test_rand(&rand_seed) % requests.size()]);
71a7433515114ae725c3427cd510f76b84107170a1Andreas Gampe        }
72a7433515114ae725c3427cd510f76b84107170a1Andreas Gampe      }
73a7433515114ae725c3427cd510f76b84107170a1Andreas Gampe
748f23620d45399286564986d2541cda761b3fe0acMathieu Chartier      // Check the zygote flag for the first phase.
758f23620d45399286564986d2541cda761b3fe0acMathieu Chartier      if (phase == 0) {
768f23620d45399286564986d2541cda761b3fe0acMathieu Chartier        for (const auto& pair : requests) {
778f23620d45399286564986d2541cda761b3fe0acMathieu Chartier          mirror::Object* obj = pair.first;
788f23620d45399286564986d2541cda761b3fe0acMathieu Chartier          ASSERT_FALSE(los->IsZygoteLargeObject(self, obj));
798f23620d45399286564986d2541cda761b3fe0acMathieu Chartier        }
808f23620d45399286564986d2541cda761b3fe0acMathieu Chartier        los->SetAllLargeObjectsAsZygoteObjects(self);
818f23620d45399286564986d2541cda761b3fe0acMathieu Chartier        for (const auto& pair : requests) {
828f23620d45399286564986d2541cda761b3fe0acMathieu Chartier          mirror::Object* obj = pair.first;
838f23620d45399286564986d2541cda761b3fe0acMathieu Chartier          ASSERT_TRUE(los->IsZygoteLargeObject(self, obj));
848f23620d45399286564986d2541cda761b3fe0acMathieu Chartier        }
858f23620d45399286564986d2541cda761b3fe0acMathieu Chartier      }
868f23620d45399286564986d2541cda761b3fe0acMathieu Chartier
87a7433515114ae725c3427cd510f76b84107170a1Andreas Gampe      // Free 1 / 2 the allocations the first phase, and all the second phase.
888f23620d45399286564986d2541cda761b3fe0acMathieu Chartier      size_t limit = phase == 0 ? requests.size() / 2 : 0;
89a7433515114ae725c3427cd510f76b84107170a1Andreas Gampe      while (requests.size() > limit) {
90a7433515114ae725c3427cd510f76b84107170a1Andreas Gampe        mirror::Object* obj = requests.back().first;
91a7433515114ae725c3427cd510f76b84107170a1Andreas Gampe        size_t request_size = requests.back().second;
92a7433515114ae725c3427cd510f76b84107170a1Andreas Gampe        requests.pop_back();
9313735955f39b3b304c37d2b2840663c131262c18Ian Rogers        uint8_t magic = (request_size & 0xFF) | 1;
94a7433515114ae725c3427cd510f76b84107170a1Andreas Gampe        for (size_t k = 0; k < request_size; ++k) {
9513735955f39b3b304c37d2b2840663c131262c18Ian Rogers          ASSERT_EQ(reinterpret_cast<const uint8_t*>(obj)[k], magic);
96a7433515114ae725c3427cd510f76b84107170a1Andreas Gampe        }
97a7433515114ae725c3427cd510f76b84107170a1Andreas Gampe        ASSERT_GE(los->Free(Thread::Current(), obj), request_size);
98a7433515114ae725c3427cd510f76b84107170a1Andreas Gampe      }
99a7433515114ae725c3427cd510f76b84107170a1Andreas Gampe    }
100af4edbd2b77fef0eee3827eb30cc1a0e8e6efeb1Mathieu Chartier    // Test that dump doesn't crash.
101af4edbd2b77fef0eee3827eb30cc1a0e8e6efeb1Mathieu Chartier    los->Dump(LOG(INFO));
102a7433515114ae725c3427cd510f76b84107170a1Andreas Gampe
1034460a84be92b5a94ecfb5c650aef4945ab849c93Hiroshi Yamauchi    size_t bytes_allocated = 0, bytes_tl_bulk_allocated;
104a7433515114ae725c3427cd510f76b84107170a1Andreas Gampe    // Checks that the coalescing works.
1058f23620d45399286564986d2541cda761b3fe0acMathieu Chartier    mirror::Object* obj = los->Alloc(self, 100 * MB, &bytes_allocated, nullptr,
1064460a84be92b5a94ecfb5c650aef4945ab849c93Hiroshi Yamauchi                                     &bytes_tl_bulk_allocated);
107a7433515114ae725c3427cd510f76b84107170a1Andreas Gampe    EXPECT_TRUE(obj != nullptr);
108a7433515114ae725c3427cd510f76b84107170a1Andreas Gampe    los->Free(Thread::Current(), obj);
109a7433515114ae725c3427cd510f76b84107170a1Andreas Gampe
110a7433515114ae725c3427cd510f76b84107170a1Andreas Gampe    EXPECT_EQ(0U, los->GetBytesAllocated());
111a7433515114ae725c3427cd510f76b84107170a1Andreas Gampe    EXPECT_EQ(0U, los->GetObjectsAllocated());
112a7433515114ae725c3427cd510f76b84107170a1Andreas Gampe    delete los;
113a7433515114ae725c3427cd510f76b84107170a1Andreas Gampe  }
114a7433515114ae725c3427cd510f76b84107170a1Andreas Gampe}
115a7433515114ae725c3427cd510f76b84107170a1Andreas Gampe
116b870823dd181571e10ecda58a6b5660e62bb18beAndreas Gampeclass AllocRaceTask : public Task {
117b870823dd181571e10ecda58a6b5660e62bb18beAndreas Gampe public:
118b870823dd181571e10ecda58a6b5660e62bb18beAndreas Gampe  AllocRaceTask(size_t id, size_t iterations, size_t size, LargeObjectSpace* los) :
119b870823dd181571e10ecda58a6b5660e62bb18beAndreas Gampe    id_(id), iterations_(iterations), size_(size), los_(los) {}
120b870823dd181571e10ecda58a6b5660e62bb18beAndreas Gampe
121b870823dd181571e10ecda58a6b5660e62bb18beAndreas Gampe  void Run(Thread* self) {
122b870823dd181571e10ecda58a6b5660e62bb18beAndreas Gampe    for (size_t i = 0; i < iterations_ ; ++i) {
1234460a84be92b5a94ecfb5c650aef4945ab849c93Hiroshi Yamauchi      size_t alloc_size, bytes_tl_bulk_allocated;
1244460a84be92b5a94ecfb5c650aef4945ab849c93Hiroshi Yamauchi      mirror::Object* ptr = los_->Alloc(self, size_, &alloc_size, nullptr,
1254460a84be92b5a94ecfb5c650aef4945ab849c93Hiroshi Yamauchi                                        &bytes_tl_bulk_allocated);
126b870823dd181571e10ecda58a6b5660e62bb18beAndreas Gampe
127b870823dd181571e10ecda58a6b5660e62bb18beAndreas Gampe      NanoSleep((id_ + 3) * 1000);  // (3+id) mu s
128b870823dd181571e10ecda58a6b5660e62bb18beAndreas Gampe
129b870823dd181571e10ecda58a6b5660e62bb18beAndreas Gampe      los_->Free(self, ptr);
130b870823dd181571e10ecda58a6b5660e62bb18beAndreas Gampe    }
131b870823dd181571e10ecda58a6b5660e62bb18beAndreas Gampe  }
132b870823dd181571e10ecda58a6b5660e62bb18beAndreas Gampe
133b870823dd181571e10ecda58a6b5660e62bb18beAndreas Gampe  virtual void Finalize() {
134b870823dd181571e10ecda58a6b5660e62bb18beAndreas Gampe    delete this;
135b870823dd181571e10ecda58a6b5660e62bb18beAndreas Gampe  }
136b870823dd181571e10ecda58a6b5660e62bb18beAndreas Gampe
137b870823dd181571e10ecda58a6b5660e62bb18beAndreas Gampe private:
138b870823dd181571e10ecda58a6b5660e62bb18beAndreas Gampe  size_t id_;
139b870823dd181571e10ecda58a6b5660e62bb18beAndreas Gampe  size_t iterations_;
140b870823dd181571e10ecda58a6b5660e62bb18beAndreas Gampe  size_t size_;
141b870823dd181571e10ecda58a6b5660e62bb18beAndreas Gampe  LargeObjectSpace* los_;
142b870823dd181571e10ecda58a6b5660e62bb18beAndreas Gampe};
143b870823dd181571e10ecda58a6b5660e62bb18beAndreas Gampe
144b870823dd181571e10ecda58a6b5660e62bb18beAndreas Gampevoid LargeObjectSpaceTest::RaceTest() {
145b870823dd181571e10ecda58a6b5660e62bb18beAndreas Gampe  for (size_t los_type = 0; los_type < 2; ++los_type) {
146b870823dd181571e10ecda58a6b5660e62bb18beAndreas Gampe    LargeObjectSpace* los = nullptr;
147b870823dd181571e10ecda58a6b5660e62bb18beAndreas Gampe    if (los_type == 0) {
148b870823dd181571e10ecda58a6b5660e62bb18beAndreas Gampe      los = space::LargeObjectMapSpace::Create("large object space");
149b870823dd181571e10ecda58a6b5660e62bb18beAndreas Gampe    } else {
150b870823dd181571e10ecda58a6b5660e62bb18beAndreas Gampe      los = space::FreeListSpace::Create("large object space", nullptr, 128 * MB);
151b870823dd181571e10ecda58a6b5660e62bb18beAndreas Gampe    }
152b870823dd181571e10ecda58a6b5660e62bb18beAndreas Gampe
153b870823dd181571e10ecda58a6b5660e62bb18beAndreas Gampe    Thread* self = Thread::Current();
154b870823dd181571e10ecda58a6b5660e62bb18beAndreas Gampe    ThreadPool thread_pool("Large object space test thread pool", kNumThreads);
155b870823dd181571e10ecda58a6b5660e62bb18beAndreas Gampe    for (size_t i = 0; i < kNumThreads; ++i) {
156b870823dd181571e10ecda58a6b5660e62bb18beAndreas Gampe      thread_pool.AddTask(self, new AllocRaceTask(i, kNumIterations, 16 * KB, los));
157b870823dd181571e10ecda58a6b5660e62bb18beAndreas Gampe    }
158b870823dd181571e10ecda58a6b5660e62bb18beAndreas Gampe
159b870823dd181571e10ecda58a6b5660e62bb18beAndreas Gampe    thread_pool.StartWorkers(self);
160b870823dd181571e10ecda58a6b5660e62bb18beAndreas Gampe
161b870823dd181571e10ecda58a6b5660e62bb18beAndreas Gampe    thread_pool.Wait(self, true, false);
162b870823dd181571e10ecda58a6b5660e62bb18beAndreas Gampe
163b870823dd181571e10ecda58a6b5660e62bb18beAndreas Gampe    delete los;
164b870823dd181571e10ecda58a6b5660e62bb18beAndreas Gampe  }
165b870823dd181571e10ecda58a6b5660e62bb18beAndreas Gampe}
166a7433515114ae725c3427cd510f76b84107170a1Andreas Gampe
167a7433515114ae725c3427cd510f76b84107170a1Andreas GampeTEST_F(LargeObjectSpaceTest, LargeObjectTest) {
168a7433515114ae725c3427cd510f76b84107170a1Andreas Gampe  LargeObjectTest();
169a7433515114ae725c3427cd510f76b84107170a1Andreas Gampe}
170a7433515114ae725c3427cd510f76b84107170a1Andreas Gampe
171b870823dd181571e10ecda58a6b5660e62bb18beAndreas GampeTEST_F(LargeObjectSpaceTest, RaceTest) {
172b870823dd181571e10ecda58a6b5660e62bb18beAndreas Gampe  RaceTest();
173b870823dd181571e10ecda58a6b5660e62bb18beAndreas Gampe}
174b870823dd181571e10ecda58a6b5660e62bb18beAndreas Gampe
175a7433515114ae725c3427cd510f76b84107170a1Andreas Gampe}  // namespace space
176a7433515114ae725c3427cd510f76b84107170a1Andreas Gampe}  // namespace gc
177a7433515114ae725c3427cd510f76b84107170a1Andreas Gampe}  // namespace art
178