• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**
2  * Copyright (c) 2021-2022 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 <sys/mman.h>
18 
19 #include "libpandabase/mem/mem.h"
20 #include "libpandabase/os/mem.h"
21 #include "libpandabase/utils/asan_interface.h"
22 #include "runtime/include/class_linker.h"
23 #include "runtime/include/runtime.h"
24 #include "runtime/mem/freelist_allocator-inl.h"
25 #include "runtime/mem/gc/hybrid-gc/hybrid_object_allocator.h"
26 #include "runtime/mem/humongous_obj_allocator-inl.h"
27 #include "runtime/tests/class_linker_test_extension.h"
28 
29 namespace panda::mem {
30 class HybridObjectAllocatorTest : public testing::Test {
31 public:
HybridObjectAllocatorTest()32     HybridObjectAllocatorTest()
33     {
34         options_.SetShouldLoadBootPandaFiles(false);
35         options_.SetShouldInitializeIntrinsics(false);
36         Runtime::Create(options_);
37         thread_ = panda::MTManagedThread::GetCurrent();
38         thread_->ManagedCodeBegin();
39     }
~HybridObjectAllocatorTest()40     ~HybridObjectAllocatorTest()
41     {
42         thread_->ManagedCodeEnd();
43         Runtime::Destroy();
44     }
45 
RemovePools(HybridObjectAllocator * allocator)46     void RemovePools(HybridObjectAllocator *allocator)
47     {
48         auto large_allocator = allocator->GetLargeObjectAllocator();
49         large_allocator->VisitAndRemoveAllPools(
50             [](void *mem, size_t size) { PoolManager::GetMmapMemPool()->FreePool(mem, size); });
51 
52         auto humongous_allocator = allocator->GetHumongousObjectAllocator();
53         humongous_allocator->VisitAndRemoveAllPools(
54             [](void *mem, size_t size) { PoolManager::GetMmapMemPool()->FreePool(mem, size); });
55     }
56 
Free(HybridObjectAllocator * allocator,void * mem)57     void Free(HybridObjectAllocator *allocator, void *mem)
58     {
59         auto large_allocator = allocator->GetLargeObjectAllocator();
60         if (large_allocator->AllocatedByFreeListAllocator(mem)) {
61             large_allocator->Free(mem);
62             return;
63         }
64 
65         auto humongous_allocator = allocator->GetHumongousObjectAllocator();
66         if (humongous_allocator->AllocatedByHumongousObjAllocator(mem)) {
67             humongous_allocator->Free(mem);
68             return;
69         }
70 
71         UNREACHABLE();
72     }
73 
AllocatedByLargeObjAllocator(FreeListAllocator<ObjectAllocConfig> * allocator,void * mem)74     bool AllocatedByLargeObjAllocator(FreeListAllocator<ObjectAllocConfig> *allocator, void *mem)
75     {
76         return allocator->AllocatedByFreeListAllocator(mem);
77     }
78 
AllocatedByHumongousObjAllocator(HumongousObjAllocator<ObjectAllocConfig> * allocator,void * mem)79     bool AllocatedByHumongousObjAllocator(HumongousObjAllocator<ObjectAllocConfig> *allocator, void *mem)
80     {
81         return allocator->AllocatedByHumongousObjAllocator(mem);
82     }
83 
84 protected:
85     panda::MTManagedThread *thread_;
86     RuntimeOptions options_;
87 };
88 
TEST_F(HybridObjectAllocatorTest,AllocateInLargeAllocator)89 TEST_F(HybridObjectAllocatorTest, AllocateInLargeAllocator)
90 {
91     mem::MemStatsType *mem_stats = new mem::MemStatsType();
92     HybridObjectAllocator allocator(mem_stats, false);
93     ClassLinker *class_linker = Runtime::GetCurrent()->GetClassLinker();
94     ASSERT_NE(class_linker, nullptr);
95     LanguageContext ctx = Runtime::GetCurrent()->GetLanguageContext(panda_file::SourceLang::PANDA_ASSEMBLY);
96 
97     auto allocate_helper = [&ctx](HybridObjectAllocator &hybrid_object_allocator, ClassRoot class_root,
98                                   size_t size) -> void * {
99         Class *klass = nullptr;
100         klass = Runtime::GetCurrent()->GetClassLinker()->GetExtension(ctx)->GetClassRoot(class_root);
101         return hybrid_object_allocator.AllocateInLargeAllocator(size, DEFAULT_ALIGNMENT, klass);
102     };
103 
104     void *mem = nullptr;
105     mem = allocate_helper(allocator, ClassRoot::CLASS, HybridObjectAllocator::GetLargeThreshold());
106     ASSERT_EQ(mem, nullptr);
107 
108     mem = allocate_helper(allocator, ClassRoot::ARRAY_I8, HybridObjectAllocator::GetLargeThreshold());
109     ASSERT_NE(mem, nullptr);
110     ASSERT_TRUE(AllocatedByLargeObjAllocator(allocator.GetLargeObjectAllocator(), mem));
111     Free(&allocator, mem);
112 
113     size_t size = HybridObjectAllocator::LargeObjectAllocator::GetMaxSize() + 1;
114     mem = allocate_helper(allocator, ClassRoot::ARRAY_I8, size);
115     ASSERT_NE(mem, nullptr);
116     ASSERT_TRUE(AllocatedByHumongousObjAllocator(allocator.GetHumongousObjectAllocator(), mem));
117     Free(&allocator, mem);
118 
119     mem = allocate_helper(allocator, ClassRoot::STRING, HybridObjectAllocator::GetLargeThreshold());
120     ASSERT_NE(mem, nullptr);
121     ASSERT_TRUE(AllocatedByLargeObjAllocator(allocator.GetLargeObjectAllocator(), mem));
122     Free(&allocator, mem);
123 
124     size = HybridObjectAllocator::LargeObjectAllocator::GetMaxSize() + 1;
125     mem = allocate_helper(allocator, ClassRoot::STRING, size);
126     ASSERT_NE(mem, nullptr);
127     ASSERT_TRUE(AllocatedByHumongousObjAllocator(allocator.GetHumongousObjectAllocator(), mem));
128     Free(&allocator, mem);
129 
130     RemovePools(&allocator);
131 
132     delete mem_stats;
133 }
134 
TEST_F(HybridObjectAllocatorTest,AllocateInNonLargeAllocator)135 TEST_F(HybridObjectAllocatorTest, AllocateInNonLargeAllocator)
136 {
137     mem::MemStatsType *mem_stats = new mem::MemStatsType();
138     HybridObjectAllocator allocator(mem_stats, false);
139 
140     void *mem = allocator.Allocate(HybridObjectAllocator::GetLargeThreshold(), DEFAULT_ALIGNMENT, nullptr);
141     ASSERT_NE(mem, nullptr);
142 
143     delete mem_stats;
144 }
145 
146 }  // namespace panda::mem
147