• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021 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 #ifndef ECMASCRIPT_MEM_TLAB_ALLOCATOR_INL_H
17 #define ECMASCRIPT_MEM_TLAB_ALLOCATOR_INL_H
18 
19 #include "ecmascript/mem/tlab_allocator.h"
20 
21 #include "ecmascript/free_object.h"
22 #include "ecmascript/mem/full_gc.h"
23 #include "ecmascript/mem/heap-inl.h"
24 
25 namespace panda::ecmascript {
26 static constexpr size_t MIN_BUFFER_SIZE = 31_KB;
27 static constexpr size_t SMALL_OBJECT_SIZE = 8_KB;
28 
TlabAllocator(Heap * heap)29 TlabAllocator::TlabAllocator(Heap *heap)
30     : heap_(heap), enableExpandYoung_(true)
31 {
32     size_t maxOldSpaceCapacity = heap->GetOldSpace()->GetMaximumCapacity();
33     localSpace_ = new LocalSpace(heap, maxOldSpaceCapacity, maxOldSpaceCapacity);
34     youngAllocator_.Reset();
35 }
36 
Finalize()37 inline void TlabAllocator::Finalize()
38 {
39     if (youngAllocator_.Available() != 0) {
40         FreeObject::FillFreeObject(heap_->GetEcmaVM(), youngAllocator_.GetTop(), youngAllocator_.Available());
41         youngAllocator_.Reset();
42     }
43 
44     heap_->MergeToOldSpaceSync(localSpace_);
45 }
46 
Allocate(size_t size,MemSpaceType space)47 uintptr_t TlabAllocator::Allocate(size_t size, MemSpaceType space)
48 {
49     uintptr_t result = 0;
50     switch (space) {
51         case SEMI_SPACE:
52             result = AllocateInYoungSpace(size);
53             break;
54         case OLD_SPACE:
55             result = AllocateInOldSpace(size);
56             break;
57         case COMPRESS_SPACE:
58             result = AllocateInCompressSpace(size);
59             break;
60         default:
61             LOG_ECMA(FATAL) << "this branch is unreachable";
62             UNREACHABLE();
63     }
64     return result;
65 }
66 
AllocateInYoungSpace(size_t size)67 uintptr_t TlabAllocator::AllocateInYoungSpace(size_t size)
68 {
69     ASSERT(AlignUp(size, static_cast<size_t>(MemAlignment::MEM_ALIGN_OBJECT)) == size);
70     if (UNLIKELY(size > SMALL_OBJECT_SIZE)) {
71         uintptr_t address = heap_->AllocateYoungSync(size);
72         return address;
73     }
74     uintptr_t result = youngAllocator_.Allocate(size);
75     if (result != 0) {
76         return result;
77     }
78     if (!enableExpandYoung_ || !ExpandYoung()) {
79         enableExpandYoung_ = false;
80         return 0;
81     }
82     return youngAllocator_.Allocate(size);
83 }
84 
AllocateInCompressSpace(size_t size)85 uintptr_t TlabAllocator::AllocateInCompressSpace(size_t size)
86 {
87     ASSERT(AlignUp(size, static_cast<size_t>(MemAlignment::MEM_ALIGN_OBJECT)) == size);
88     size = AlignUp(size, static_cast<size_t>(MemAlignment::MEM_ALIGN_OBJECT));
89     uintptr_t result = localSpace_->Allocate(size, true);
90     ASSERT(result != 0);
91     return result;
92 }
93 
AllocateInOldSpace(size_t size)94 uintptr_t TlabAllocator::AllocateInOldSpace(size_t size)
95 {
96     ASSERT(AlignUp(size, static_cast<size_t>(MemAlignment::MEM_ALIGN_OBJECT)) == size);
97     size = AlignUp(size, static_cast<size_t>(MemAlignment::MEM_ALIGN_OBJECT));
98     // 1. Allocate from freelist in compress allocator
99     uintptr_t result = localSpace_->Allocate(size, false);
100     if (result == 0) {
101         // 2. Expand region from old space
102         ExpandCompressFromOld(size);
103         result = localSpace_->Allocate(size, true);
104     }
105     ASSERT(result != 0);
106     return result;
107 }
108 
ExpandYoung()109 bool TlabAllocator::ExpandYoung()
110 {
111     uintptr_t buffer = heap_->AllocateYoungSync(MIN_BUFFER_SIZE);
112     if (buffer == 0) {
113         if (youngAllocator_.Available() != 0) {
114             FreeObject::FillFreeObject(heap_->GetEcmaVM(), youngAllocator_.GetTop(), youngAllocator_.Available());
115         }
116         return false;
117     }
118     uintptr_t end = buffer + MIN_BUFFER_SIZE;
119 
120     if (buffer == youngAllocator_.GetEnd()) {
121         buffer = youngAllocator_.GetTop();
122     } else {
123         if (youngAllocator_.Available() != 0) {
124             FreeObject::FillFreeObject(heap_->GetEcmaVM(), youngAllocator_.GetTop(), youngAllocator_.Available());
125         }
126     }
127     youngAllocator_.Reset(buffer, end);
128     return true;
129 }
130 
ExpandCompressFromOld(size_t size)131 bool TlabAllocator::ExpandCompressFromOld(size_t size)
132 {
133     auto region = heap_->GetOldSpace()->TryToGetExclusiveRegion(size);
134     if (region != nullptr) {
135         localSpace_->AddRegionToList(region);
136         return true;
137     }
138     return false;
139 }
140 }  // namespace panda::ecmascript
141 #endif  // ECMASCRIPT_MEM_TLAB_ALLOCATOR_INL_H
142