1 /**
2 * Copyright (c) 2021-2024 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "gtest/gtest.h"
17 #include "runtime/include/runtime.h"
18 #include "runtime/include/mem/panda_containers.h"
19 #include "runtime/mem/runslots_allocator-inl.h"
20
21 namespace ark::mem::test {
22
23 class PandaContainersTest : public testing::Test {
24 public:
PandaContainersTest()25 PandaContainersTest()
26 {
27 RuntimeOptions options;
28 options.SetShouldLoadBootPandaFiles(false);
29 options.SetShouldInitializeIntrinsics(false);
30 options.SetLimitStandardAlloc(true);
31 options.SetInternalAllocatorType("panda_allocators");
32 Runtime::Create(options);
33 thread_ = ark::MTManagedThread::GetCurrent();
34 thread_->ManagedCodeBegin();
35 }
36
37 template <class T>
GetLocalObjects(T * allocator)38 size_t GetLocalObjects(T *allocator)
39 {
40 size_t numObjects = 0;
41 allocator->IterateOverObjects([&numObjects]([[maybe_unused]] ObjectHeader *obj) { numObjects++; });
42 return numObjects;
43 }
44
~PandaContainersTest()45 ~PandaContainersTest() override
46 {
47 thread_->ManagedCodeEnd();
48 Runtime::Destroy();
49 }
50
51 NO_COPY_SEMANTIC(PandaContainersTest);
52 NO_MOVE_SEMANTIC(PandaContainersTest);
53
54 private:
55 ark::MTManagedThread *thread_ {};
56 };
57
58 constexpr size_t MAX_SIZE = InternalAllocator<>::LocalSmallObjectAllocator::GetMaxSize();
TEST_F(PandaContainersTest,LocalTest)59 TEST_F(PandaContainersTest, LocalTest)
60 {
61 ASSERT(!Runtime::GetCurrent()->GetOptions().UseMallocForInternalAllocations());
62 auto localAllocator = ark::ManagedThread::GetCurrent()->GetLocalInternalAllocator();
63 ASSERT_EQ(GetLocalObjects(localAllocator), 0);
64 {
65 PandaVectorTL<uint8_t> vectorLocal;
66 vectorLocal.push_back(0);
67 // std::vector allocated memory block for it's elements via local_allocator
68 ASSERT_EQ(GetLocalObjects(localAllocator), 1);
69 for (size_t i = 1; i < MAX_SIZE; i++) {
70 vectorLocal.push_back(i % MAX_SIZE);
71 if (vectorLocal.capacity() <= MAX_SIZE) {
72 // Threre is 1 memory block for all elements
73 ASSERT_EQ(GetLocalObjects(localAllocator), 1);
74 } else {
75 // When vector size exceeds MAX_SIZE=256 bytes, we allocate it without thread-local runslots allocator
76 ASSERT_EQ(GetLocalObjects(localAllocator), 0);
77 }
78 }
79 // Simple check on data consistency
80 for (size_t i = 0; i < MAX_SIZE; i++) {
81 ASSERT_EQ(vectorLocal.at(i), i % MAX_SIZE);
82 }
83 vectorLocal.push_back(0);
84 // When vector size exceeds MAX_SIZE=256 bytes, we allocate it without thread-local runslots allocator
85 ASSERT_EQ(GetLocalObjects(localAllocator), 0);
86 }
87 ASSERT_EQ(GetLocalObjects(localAllocator), 0);
88 }
89
90 // Check that, when we use GLOBAL scope, there is no memory in thread-local allocator
TEST_F(PandaContainersTest,GlobalTest)91 TEST_F(PandaContainersTest, GlobalTest)
92 {
93 auto localAllocator = ark::ManagedThread::GetCurrent()->GetLocalInternalAllocator();
94 ASSERT_EQ(GetLocalObjects(localAllocator), 0);
95 {
96 PandaVector<uint8_t> vectorGlobal;
97 vectorGlobal.push_back(0);
98 ASSERT_EQ(GetLocalObjects(localAllocator), 0);
99 for (size_t i = 1; i < MAX_SIZE; i++) {
100 vectorGlobal.push_back(i % MAX_SIZE);
101 ASSERT_EQ(GetLocalObjects(localAllocator), 0);
102 }
103
104 for (size_t i = 0; i < MAX_SIZE; i++) {
105 ASSERT_EQ(vectorGlobal.at(i), i % MAX_SIZE);
106 }
107 vectorGlobal.push_back(0);
108 ASSERT_EQ(GetLocalObjects(localAllocator), 0);
109 }
110 ASSERT_EQ(GetLocalObjects(localAllocator), 0);
111 }
112
113 } // namespace ark::mem::test
114